1+ // yes i know the page is the exact same as index.tsx, it's just temporary lol
2+
13"use client" ;
24
35import React , { useState , useEffect } from "react" ;
46import { FaCloudUploadAlt , FaDatabase } from "react-icons/fa" ;
5- import initSqlJs , { Database } from "sql.js" ;
7+ import initSqlJs from "sql.js" ;
68
79import Navbar from "@/components/Navbar" ;
810
@@ -30,30 +32,13 @@ const Tabs = React.memo(({ tabs, activeTab, onTabChange }: TabsProps) => (
3032 </ div >
3133) ) ;
3234
33- // Everything will die if i remove this
3435Tabs . displayName = "Tabs" ;
3536
3637export default function Home ( ) {
3738 const [ file , setFile ] = useState < File | null > ( null ) ;
38- const [ db , setDb ] = useState < Database | null > ( null ) ;
39- const [ queryResult , setQueryResult ] = useState < any > ( null ) ;
4039 const [ data , setData ] = useState < { [ key : string ] : any [ ] } | null > ( null ) ;
4140 const [ activeTab , setActiveTab ] = useState < string > ( "" ) ;
4241 const [ isDarkMode , setIsDarkMode ] = useState < boolean > ( false ) ;
43- const [ isLoading , setIsLoading ] = useState < boolean > ( false ) ;
44-
45- useEffect ( ( ) => {
46- const loadDb = async ( ) => {
47- const SQL = await initSqlJs ( {
48- locateFile : ( ) => "/sql-wasm.wasm" , // Ensure the correct path
49- } ) ;
50- const database = new SQL . Database ( ) ;
51-
52- setDb ( database ) ;
53- } ;
54-
55- loadDb ( ) ;
56- } , [ ] ) ;
5742
5843 useEffect ( ( ) => {
5944 const systemPrefersDark = window . matchMedia (
@@ -73,50 +58,63 @@ export default function Home() {
7358 }
7459 } ;
7560
76- const handleUpload = async ( event : React . ChangeEvent < HTMLInputElement > ) => {
77- const file = event . target . files ?. [ 0 ] ;
61+ const handleUpload = async ( ) => {
62+ if ( ! file ) return alert ( "Please select a file first." ) ;
63+
64+ if ( file . size > 50 * 1024 * 1024 ) {
65+ return alert (
66+ "File size exceeds the 50MB limit. That's a good thing though because unless you're NASA, your pc would probably explode." ,
67+ ) ;
68+ }
69+
7870 if ( ! file ) return ;
79-
71+
8072 const reader = new FileReader ( ) ;
73+
8174 reader . onload = async ( e ) => {
8275 const arrayBuffer = e . target ?. result as ArrayBuffer ;
76+
8377 if ( ! arrayBuffer ) return ;
84-
78+
8579 const SQL = await initSqlJs ( ) ;
8680 const database = new SQL . Database ( new Uint8Array ( arrayBuffer ) ) ;
87- setDb ( database ) ;
88-
81+
8982 // Get all table names
9083 const tablesResult = database . exec (
91- "SELECT name FROM sqlite_master WHERE type='table'"
84+ "SELECT name FROM sqlite_master WHERE type='table'" ,
9285 ) ;
93-
86+
9487 if ( tablesResult . length === 0 ) return ;
95-
88+
9689 const tableNames = tablesResult [ 0 ] . values . flat ( ) as string [ ] ;
90+
9791 setActiveTab ( tableNames [ 0 ] ) ; // Set the first table as active
98-
92+
9993 // Fetch data for each table
10094 const dbData : { [ key : string ] : any [ ] } = { } ;
95+
10196 for ( const table of tableNames ) {
10297 const result = database . exec ( `SELECT * FROM ${ table } ` ) ;
98+
10399 if ( result . length > 0 ) {
104100 const columns = result [ 0 ] . columns ;
105101 const rows = result [ 0 ] . values . map ( ( row ) =>
106- Object . fromEntries ( columns . map ( ( col , i ) => [ col , row [ i ] ] ) )
102+ Object . fromEntries (
103+ columns . map ( ( col , i ) => [ col , row [ i ] ] ) ,
104+ ) ,
107105 ) ;
106+
108107 dbData [ table ] = rows ;
109108 } else {
110109 dbData [ table ] = [ ] ;
111110 }
112111 }
113-
112+
114113 setData ( dbData ) ;
115114 } ;
116-
115+
117116 reader . readAsArrayBuffer ( file ) ;
118117 } ;
119-
120118
121119 const renderTable = ( tableData : any [ ] ) => {
122120 if ( ! tableData || tableData . length === 0 )
@@ -128,6 +126,9 @@ export default function Home() {
128126 < table className = "w-full text-left border-collapse border border-gray-200 dark:border-gray-700" >
129127 < thead >
130128 < tr className = "bg-gray-200 dark:bg-gray-800" >
129+ < th className = "p-3 border border-gray-300 font-medium text-gray-700 dark:text-gray-300" >
130+ #
131+ </ th >
131132 { columns . map ( ( col , index ) => (
132133 < th
133134 key = { index }
@@ -148,6 +149,9 @@ export default function Home() {
148149 : "bg-gray-50 dark:bg-gray-800"
149150 } hover:bg-gray-100 dark:hover:bg-gray-700`}
150151 >
152+ < td className = "p-3 border border-gray-300 dark:border-gray-700" >
153+ { rowIndex + 1 }
154+ </ td >
151155 { columns . map ( ( col , colIndex ) => (
152156 < td
153157 key = { colIndex }
@@ -163,22 +167,14 @@ export default function Home() {
163167 ) ;
164168 } ;
165169
166- const Spinner = ( ) => (
167- < div className = "flex justify-center items-center mb-4" >
168- < div className = "animate-spin rounded-full h-8 w-8 border-t-2 border-blue-500" />
169- </ div >
170- ) ;
171-
172170 return (
173171 < div style = { { color : "var(--text-color)" } } >
174172 < Navbar />
175173
176174 < div className = "flex justify-center mb-12" >
177175 < div
178176 className = "w-full max-w-3xl p-6 shadow rounded-lg"
179- style = { {
180- backgroundColor : "var(--upload-box-bg)" ,
181- } }
177+ style = { { backgroundColor : "var(--upload-box-bg)" } }
182178 >
183179 < h2 className = "text-lg text-center font-semibold mb-4" >
184180 Upload SQLite File
@@ -191,7 +187,6 @@ export default function Home() {
191187 type = "file"
192188 onChange = { handleFileChange }
193189 />
194-
195190 < label
196191 className = "px-6 py-2 rounded hover:bg-blue-600 transition inline-flex items-center gap-2"
197192 htmlFor = "file-upload"
@@ -224,15 +219,14 @@ export default function Home() {
224219 </ button >
225220 </ div >
226221
227- < h2 className = "text-lg font-semibold mb-4 text-center" >
228- btw, there's a maximum upload limit of 50MB
229- </ h2 >
222+ < p className = "text-lg font-semibold mb-4 text-center bg-gradient-to-r from-purple-400 via-pink-500 to-red-500 bg-clip-text text-transparent" >
223+ Update: There is no upload limit anymore, it's all
224+ done in your browser! Better for security and privacy.
225+ </ p >
230226 </ div >
231227 </ div >
232228
233- { isLoading ? (
234- < Spinner />
235- ) : data ? (
229+ { data ? (
236230 < div className = "mb-8" >
237231 < Tabs
238232 activeTab = { activeTab }
@@ -260,23 +254,20 @@ export default function Home() {
260254 How does it work?
261255 </ h2 >
262256 < p className = "mb-4" >
263- Whenever you upload a SQLite file, it gets sent to the
264- server where the entire contents gets read and returned
265- in a massive JSON object, which is parsed into multiple
266- tables .
257+ When you upload your SQLite file, it gets processed
258+ locally on your device and is stored in RAM. It then
259+ reads the data of the database and visualizes it in the
260+ browser .
267261 </ p >
268262
269263 < h2 className = "text-lg font-semibold mb-4" >
270264 Do my files get saved?
271265 </ h2 >
272- < p className = "mb-4" >
273- Only when it's being processed. Once it's
274- done, the file is immediately deleted, so no worries
275- about your data being stored.
276- </ p >
266+ < p className = "mb-4" > Nope, it's all locally done!</ p >
277267 < p className = "mb-4" >
278268 A reminder that the site is open source, so you can view
279- the code! Check the first link at the top of the page.
269+ the code! Click the "View on GitHub" button to
270+ see more.
280271 </ p >
281272
282273 < h2 className = "text-lg font-semibold mb-4" >
0 commit comments