1-
21import { Separator } from "@/components/ui/separator" ;
3- import { extractDate } from "@/lib/time" ;
4- import { Script , AppVersion } from "@/lib/types" ;
52import { fetchVersions } from "@/lib/data" ;
3+ import { extractDate } from "@/lib/time" ;
4+ import { AppVersion , Script } from "@/lib/types" ;
65
76import { X } from "lucide-react" ;
87import Image from "next/image" ;
98
9+ import { basePath } from "@/config/siteConfig" ;
10+ import { useEffect , useState } from "react" ;
1011import { getDisplayValueFromType } from "./ScriptInfoBlocks" ;
1112import Alerts from "./ScriptItems/Alerts" ;
1213import Buttons from "./ScriptItems/Buttons" ;
1314import DefaultPassword from "./ScriptItems/DefaultPassword" ;
14- import DefaultSettings from "./ScriptItems/DefaultSettings" ;
1515import Description from "./ScriptItems/Description" ;
1616import InstallCommand from "./ScriptItems/InstallCommand" ;
1717import InterFaces from "./ScriptItems/InterFaces" ;
1818import Tooltips from "./ScriptItems/Tooltips" ;
19- import { basePath } from "@/config/siteConfig" ;
20- import { useEffect , useState } from "react" ;
2119
22-
23- function ScriptItem ( {
24- item,
25- setSelectedScript,
26- } : {
27- item : Script ;
28- setSelectedScript : ( script : string | null ) => void ;
29- } ) {
20+ function ScriptItem ( { item, setSelectedScript } : { item : Script ; setSelectedScript : ( script : string | null ) => void } ) {
3021 const closeScript = ( ) => {
3122 window . history . pushState ( { } , document . title , window . location . pathname ) ;
3223 setSelectedScript ( null ) ;
3324 } ;
3425 const [ versions , setVersions ] = useState < AppVersion [ ] > ( [ ] ) ;
3526
36-
3727 useEffect ( ( ) => {
3828 fetchVersions ( )
3929 . then ( ( fetchedVersions ) => {
@@ -68,10 +58,7 @@ function ScriptItem({
6858 className = "h-32 w-32 rounded-lg bg-accent/60 object-contain p-3 shadow-md"
6959 src = { item . logo || `/${ basePath } /logo.png` }
7060 width = { 400 }
71- onError = { ( e ) =>
72- ( ( e . currentTarget as HTMLImageElement ) . src =
73- `/${ basePath } /logo.png` )
74- }
61+ onError = { ( e ) => ( ( e . currentTarget as HTMLImageElement ) . src = `/${ basePath } /logo.png` ) }
7562 height = { 400 }
7663 alt = { item . name }
7764 unoptimized
@@ -89,35 +76,165 @@ function ScriptItem({
8976 Default OS: { os } { version }
9077 </ p >
9178 </ div >
92- < div className = "flex gap-5" >
93- < DefaultSettings item = { item } />
94- </ div >
95- < div > { versions . length === 0 ? ( < p > Loading versions...</ p > ) :
96- ( < >
97- < p className = "text-l text-foreground" > Version:</ p >
98- < p className = "text-l text-muted-foreground" > { versions . find ( ( v ) =>
99- v . name === item . slug . replace ( / [ ^ a - z 0 - 9 ] / g, '' ) ||
100- v . name . includes ( item . slug . replace ( / [ ^ a - z 0 - 9 ] / g, '' ) ) ||
101- v . name . replace ( / [ ^ a - z 0 - 9 ] / g, '' ) === item . slug . replace ( / [ ^ a - z 0 - 9 ] / g, '' )
102-
103- ) ?. version || "No Version information found"
104- } </ p >
105- < p className = "text-l text-foreground" > Latest Version changes(Pulled from newreleases.io):</ p >
106- < p className = "text-l text-muted-foreground" >
107- { ( ( ) => {
108- const matchedVersion = versions . find ( ( v ) =>
109- v . name === item . slug . replace ( / [ ^ a - z 0 - 9 ] / g, '' ) ||
110- v . name . includes ( item . slug . replace ( / [ ^ a - z 0 - 9 ] / g, '' ) ) ||
111- v . name . replace ( / [ ^ a - z 0 - 9 ] / g, '' ) === item . slug . replace ( / [ ^ a - z 0 - 9 ] / g, '' )
112- ) ;
113- return matchedVersion ?. date ?
114- extractDate ( matchedVersion . date as unknown as string ) :
115- "No date information found"
116- } ) ( ) }
117- </ p >
118- </ > )
119- }
79+ < div className = "flex min-w-[600px] flex-wrap gap-6 text-sm text-muted-foreground" >
80+ { ( ( ) => {
81+ const getDisplayValueFromRAM = ( ram : number ) =>
82+ ram >= 1024 ? `${ Math . floor ( ram / 1024 ) } GB` : `${ ram } MB` ;
83+
84+ const IconText = ( { icon, label } : { icon : React . ReactNode ; label : string } ) => (
85+ < span className = "flex items-center gap-1" >
86+ { icon }
87+ { label }
88+ </ span >
89+ ) ;
90+
91+ const CPUIcon = (
92+ < svg
93+ xmlns = "http://www.w3.org/2000/svg"
94+ className = "w-4 h-4"
95+ fill = "none"
96+ viewBox = "0 0 24 24"
97+ stroke = "currentColor"
98+ strokeWidth = { 2 }
99+ >
100+ < rect x = "9" y = "9" width = "6" height = "6" />
101+ < path d = "M3 9h2m14 0h2M3 15h2m14 0h2M9 3v2m6-2v2M9 19v2m6-2v2" />
102+ </ svg >
103+ ) ;
104+
105+ const RAMIcon = (
106+ < svg
107+ xmlns = "http://www.w3.org/2000/svg"
108+ className = "w-4 h-4"
109+ fill = "none"
110+ viewBox = "0 0 24 24"
111+ stroke = "currentColor"
112+ strokeWidth = { 2 }
113+ >
114+ < rect x = "4" y = "6" width = "16" height = "12" rx = "2" ry = "2" />
115+ < path d = "M8 6v12M16 6v12" />
116+ </ svg >
117+ ) ;
118+
119+ const HDDIcon = (
120+ < svg
121+ xmlns = "http://www.w3.org/2000/svg"
122+ className = "w-4 h-4"
123+ fill = "none"
124+ viewBox = "0 0 24 24"
125+ stroke = "currentColor"
126+ strokeWidth = { 2 }
127+ >
128+ < path d = "M4 4h16v16H4z" />
129+ < circle cx = "8" cy = "16" r = "1" />
130+ < circle cx = "16" cy = "16" r = "1" />
131+ </ svg >
132+ ) ;
133+
134+ const ResourceDisplay = ( {
135+ title,
136+ cpu,
137+ ram,
138+ hdd,
139+ } : {
140+ title : string ;
141+ cpu : number | null ;
142+ ram : number | null ;
143+ hdd : number | null ;
144+ } ) => {
145+ const getDisplayValueFromRAM = ( ram : number ) =>
146+ ram >= 1024 ? `${ Math . floor ( ram / 1024 ) } GB` : `${ ram } MB` ;
147+
148+ const IconText = ( { icon, label } : { icon : React . ReactNode ; label : string } ) => (
149+ < span className = "flex items-center gap-1 whitespace-nowrap" >
150+ { icon }
151+ { label }
152+ </ span >
153+ ) ;
154+
155+ const hasCPU = typeof cpu === "number" && cpu > 0 ;
156+ const hasRAM = typeof ram === "number" && ram > 0 ;
157+ const hasHDD = typeof hdd === "number" && hdd > 0 ;
158+
159+ if ( ! hasCPU && ! hasRAM && ! hasHDD ) return null ;
160+
161+ return (
162+ < div className = "flex flex-wrap items-center gap-1" >
163+ < span className = "font-semibold text-foreground" > { title } :</ span >
164+ { hasCPU && (
165+ < >
166+ < IconText icon = { CPUIcon } label = { `CPU: ${ cpu } vCPU` } />
167+ < span > |</ span >
168+ </ >
169+ ) }
170+ { hasRAM && (
171+ < >
172+ < IconText icon = { RAMIcon } label = { `RAM: ${ getDisplayValueFromRAM ( ram ! ) } ` } />
173+ < span > |</ span >
174+ </ >
175+ ) }
176+ { hasHDD && < IconText icon = { HDDIcon } label = { `HDD: ${ hdd } GB` } /> }
177+ </ div >
178+ ) ;
179+ } ;
180+
181+ const defaultSettings = item . install_methods . find ( ( method ) => method . type === "default" ) ;
182+ const alpineSettings = item . install_methods . find ( ( method ) => method . type === "alpine" ) ;
183+ return (
184+ < >
185+ { defaultSettings ?. resources && (
186+ < ResourceDisplay
187+ title = "Default"
188+ cpu = { defaultSettings . resources . cpu }
189+ ram = { defaultSettings . resources . ram }
190+ hdd = { defaultSettings . resources . hdd }
191+ />
192+ ) }
193+
194+ { alpineSettings ?. resources && (
195+ < ResourceDisplay
196+ title = "Alpine"
197+ cpu = { alpineSettings . resources . cpu }
198+ ram = { alpineSettings . resources . ram }
199+ hdd = { alpineSettings . resources . hdd }
200+ />
201+ ) }
202+ </ >
203+ ) ;
204+ } ) ( ) }
120205 </ div >
206+
207+ { ( ( ) => {
208+ if ( versions . length === 0 ) {
209+ return < p > Loading versions...</ p > ;
210+ }
211+
212+ const cleanSlug = item . slug . replace ( / [ ^ a - z 0 - 9 ] / gi, "" ) . toLowerCase ( ) ;
213+
214+ const matched = versions . find ( ( v ) => {
215+ const cleanName = v . name . replace ( / [ ^ a - z 0 - 9 ] / gi, "" ) . toLowerCase ( ) ;
216+ return cleanName === cleanSlug || cleanName . includes ( cleanSlug ) ;
217+ } ) ;
218+
219+ if ( ! matched ) return null ;
220+
221+ return (
222+ < div className = "flex items-center gap-2 text-sm text-muted-foreground mt-2" >
223+ < span className = "text-foreground" >
224+ Version: { matched . version } (
225+ { extractDate (
226+ matched . date instanceof Date ? matched . date . toISOString ( ) : matched . date || "" ,
227+ ) }
228+ </ span >
229+ < span
230+ title = "Crawled version from newreleases.io"
231+ className = "cursor-help rounded-full border border-green-500 px-2 py-0.5 text-xs font-semibold text-green-500"
232+ >
233+ Info
234+ </ span >
235+ </ div >
236+ ) ;
237+ } ) ( ) }
121238 </ div >
122239 </ div >
123240 </ div >
@@ -134,9 +251,7 @@ function ScriptItem({
134251 </ div >
135252 < div className = "mt-4 rounded-lg border bg-accent/50" >
136253 < div className = "flex gap-3 px-4 py-2" >
137- < h2 className = "text-lg font-semibold" >
138- How to { item . type == "misc" ? "use" : "install" }
139- </ h2 >
254+ < h2 className = "text-lg font-semibold" > How to { item . type == "misc" ? "use" : "install" } </ h2 >
140255 < Tooltips item = { item } />
141256 </ div >
142257 < Separator className = "w-full" > </ Separator >
0 commit comments