diff --git a/app.webmanifest b/app.webmanifest deleted file mode 100644 index 9df7d54..0000000 --- a/app.webmanifest +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "Dandelion", - "short_name": "ddln", - "start_url": "/", - "display": "standalone", - "display_override": ["window-controls-overlay","standalone"], - "id": "b1dbe643-36fc-4419-9448-80f32a1baa1a", - "background_color": "#000000", - "theme_color": "#000000", - - "icons": [ - { - "src": "icons/dandelion_512x512.png", - "type": "image/png", - "sizes":"512x512" - } - ], - -"screenshots" : [ - { - "src": "images/screenshot1.jpg", - "sizes": "1280x720", - "type": "image/png", - "form_factor": "wide", - "label": "Dandelion desktop" - }, - { - "src": "images/screenshot2.jpg", - "sizes": "720x1280", - "type": "image/png", - "form_factor": "narrow", - "label": "Dandelion mobile" - } -] -} \ No newline at end of file diff --git a/db.js.map b/db.js.map deleted file mode 100644 index 72953a3..0000000 --- a/db.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"db.js","sourceRoot":"","sources":["src/db.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/main b/main index fc7c2f6..8e30364 100755 Binary files a/main and b/main differ diff --git a/main.go b/main.go index 9dd45c8..fc4365f 100644 --- a/main.go +++ b/main.go @@ -11,12 +11,13 @@ import ( "os/signal" "path/filepath" "strconv" + "strings" + "sync" "syscall" "time" // "strings" - "github.com/andybalholm/brotli" "github.com/gorilla/websocket" ) @@ -60,30 +61,33 @@ func dispatchMessage(message []byte, peer *Peer) ([]byte, error) { } const ( - writeWait = 10 * time.Second + writeWait = 120 * time.Second ) type Peer struct { conn *websocket.Conn send chan []byte lastActive time.Time + closeOnce sync.Once } -// func removePeer(peerID string, peer *Peer) { -// delete(peerConnections, peerID) +func removePeer(peerID string, peer *Peer) { + delete(peerConnections, peerID) -// for userID, peers := range userPeers { -// delete(peers, peerID) -// if len(peers) == 0 { -// delete(userPeers, userID) -// } -// } + for userID, peers := range userPeers { + delete(peers, peerID) + if len(peers) == 0 { + delete(userPeers, userID) + } + } -// delete(connectionPeers, peer.conn) + delete(connectionPeers, peer.conn) -// // Close the peer's send channel -// close(peer.send) -// } + // Close the peer's send channel safely + peer.closeOnce.Do(func() { + close(peer.send) + }) +} func handleWebSocket(w http.ResponseWriter, r *http.Request) { log.Println("Websocket connection!", r.RemoteAddr) @@ -131,7 +135,10 @@ func handleWebSocket(w http.ResponseWriter, r *http.Request) { } // Clean up when the connection is closed - close(peer.send) + peer.closeOnce.Do(func() { + close(peer.send) + }) + peerID := connectionPeers[peer.conn] if peerID != "" { delete(peerConnections, peerID) @@ -186,9 +193,10 @@ var connectionPeers = make(map[*websocket.Conn]string) func handleHello(message []byte, peer *Peer) ([]byte, error) { var m struct { - Type string `json:"type"` - UserID string `json:"user_id"` - PeerID string `json:"peer_id"` + Type string `json:"type"` + UserID string `json:"user_id"` + PeerID string `json:"peer_id"` + KnownUsers []string `json:"known_users"` } if err := json.Unmarshal(message, &m); err != nil { @@ -200,6 +208,16 @@ func handleHello(message []byte, peer *Peer) ([]byte, error) { userPeers[m.UserID] = make(PeerSet) } + for _, knownUserID := range m.KnownUsers { + fmt.Printf("Adding user %s for peer %s\n", knownUserID, m.PeerID) + if userPeers[knownUserID] == nil { + userPeers[knownUserID] = make(PeerSet) + } + + userPeers[knownUserID][m.PeerID] = struct{}{} + + } + userPeers[m.UserID][m.PeerID] = struct{}{} peerConnections[m.PeerID] = peer connectionPeers[peer.conn] = m.PeerID @@ -266,46 +284,74 @@ func (w *brotliResponseWriter) Write(b []byte) (int, error) { func noDirListing(h http.Handler, root string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - // Serve index.html when root is requested - if r.URL.Path == "/" { - http.ServeFile(w, r, filepath.Join(root, "index.html")) + // For anything under /static/, we serve it, unless it's a directory + // Otherwise we serve index.html and the app does the routing nad rendering. + + log.Printf("%s %s %s", r.URL.Path, r.RemoteAddr, r.UserAgent()) + + if r.URL.Path == "/sw.js" { + http.ServeFile(w, r, filepath.Join(root, "static/sw.js")) return } - path := filepath.Join(root, r.URL.Path) - info, err := os.Stat(path) - if err != nil || info.IsDir() { - log.Printf("404 File not found/dir serving: %s to ip %s, useragent %s", r.URL.Path, r.RemoteAddr, r.UserAgent()) - http.NotFound(w, r) + if r.URL.Path == "/robots.txt" { + http.ServeFile(w, r, filepath.Join(root, "static/robots.txt")) return } - log.Printf("Serving: %s to ip %s, useragent %s", r.URL.Path, r.RemoteAddr, r.UserAgent()) + if r.URL.Path == "/favicon.ico" { + http.ServeFile(w, r, filepath.Join(root, "static/favicon.ico")) + return + } + + if strings.Contains(r.URL.Path, "/static/") { + log.Print("Serving static") + + path := filepath.Join(root, r.URL.Path) + info, err := os.Stat(path) + if err != nil || info.IsDir() { + log.Printf("404 File not found/dir") + http.NotFound(w, r) + return + } + + log.Printf("Serving") + h.ServeHTTP(w, r) + return + + } + + // // Serve index.html when root is requested + // if r.URL.Path == "/" { + log.Printf("Serving index %s", r.URL.Path) + http.ServeFile(w, r, filepath.Join(root, "/static/index.html")) + // return + // } // w.Header().Set("Cache-Control", "no-cache") // Check if client supports Brotli encoding // if strings.Contains(r.Header.Get("Accept-Encoding"), "br") { - if false { - w.Header().Set("Content-Encoding", "br") - w.Header().Del("Content-Length") // Cannot know content length with compressed data + // if false { + // w.Header().Set("Content-Encoding", "br") + // w.Header().Del("Content-Length") // Cannot know content length with compressed data - // Wrap the ResponseWriter with Brotli writer - brWriter := brotli.NewWriter(w) - defer brWriter.Close() + // // Wrap the ResponseWriter with Brotli writer + // brWriter := brotli.NewWriter(w) + // defer brWriter.Close() - // Create a ResponseWriter that writes to brWriter - bw := &brotliResponseWriter{ - ResponseWriter: w, - Writer: brWriter, - } + // // Create a ResponseWriter that writes to brWriter + // bw := &brotliResponseWriter{ + // ResponseWriter: w, + // Writer: brWriter, + // } - // Serve the file using http.ServeFile - http.ServeFile(bw, r, path) - return - } + // // Serve the file using http.ServeFile + // http.ServeFile(bw, r, path) + // return + // } - h.ServeHTTP(w, r) + // h.ServeHTTP(w, r) } } @@ -348,39 +394,39 @@ func main() { Handler: nil, // Use the default ServeMux } - // // Start the inactivity monitor goroutine - // go func() { - // ticker := time.NewTicker(10 * time.Second) - // defer ticker.Stop() + // Start the inactivity monitor goroutine + go func() { + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() - // for { - // select { - // case <-done: - // return - // case <-ticker.C: - // now := time.Now() + for { + select { + case <-done: + return + case <-ticker.C: + now := time.Now() - // // Collect inactive peers - // var inactivePeers []string - // for peerID, peer := range peerConnections { - // if now.Sub(peer.lastActive) > 60*time.Second { - // inactivePeers = append(inactivePeers, peerID) - // } - // } + // Collect inactive peers + var inactivePeers []string + for peerID, peer := range peerConnections { + if now.Sub(peer.lastActive) > 60*time.Second { + inactivePeers = append(inactivePeers, peerID) + } + } - // // Remove inactive peers - // for _, peerID := range inactivePeers { - // peer := peerConnections[peerID] + // Remove inactive peers + for _, peerID := range inactivePeers { + peer := peerConnections[peerID] - // if peer != nil { - // log.Printf("Peer %s inactive for more than 60 seconds. Closing connection.", peerID) - // peer.conn.Close() - // removePeer(peerID, peer) - // } - // } - // } - // } - // }() + if peer != nil { + log.Printf("Peer %s inactive for more than 60 seconds. Closing connection.", peerID) + peer.conn.Close() + removePeer(peerID, peer) + } + } + } + } + }() // Run a goroutine to handle graceful shutdown go func() { diff --git a/main.js.map b/main.js.map deleted file mode 100644 index 59af7f7..0000000 --- a/main.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"main.js","sourceRoot":"","sources":["src/main.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/db.ts b/src/db.ts index 2e06d51..db6632f 100644 --- a/src/db.ts +++ b/src/db.ts @@ -10,6 +10,7 @@ const postStoreName: string = "posts"; let keyBase = "dandelion_posts_v1_" let key = ""; +let version = 1; interface IDBRequestEvent extends Event { @@ -21,26 +22,29 @@ type DBError = Event & { target: { errorCode: DOMException }; }; +function upgrade_0to1(db:IDBDatabase) { + let store = db.createObjectStore(postStoreName, { keyPath: "id", autoIncrement: true }); + store.createIndex("datetimeIndex", "post_timestamp", { unique: false }); + store.createIndex("postIDIndex", "data.post_id", { unique: true }); +} + + export function openDatabase(userID: string): Promise { const dbName = `user_${userID}` return new Promise((resolve, reject) => { - const request: IDBOpenDBRequest = indexedDB.open(dbName, 1); + const request: IDBOpenDBRequest = indexedDB.open(dbName, version); request.onerror = (event: Event) => { - // Use a type assertion to access the specific properties of IDBRequest error event const errorEvent = event as IDBRequestEvent; reject(`Database error: ${errorEvent.target.error?.message}`); }; request.onupgradeneeded = (event: IDBVersionChangeEvent) => { const db: IDBDatabase = (event.target as IDBOpenDBRequest).result; - if (!db.objectStoreNames.contains(postStoreName)) { - let store = db.createObjectStore(postStoreName, { keyPath: "id", autoIncrement: true }); - store.createIndex("datetimeIndex", "post_timestamp", { unique: false }); - store.createIndex("postIDIndex", "data.post_id", { unique: true }); - } + upgrade_0to1(db); + }; request.onsuccess = (event: Event) => { @@ -50,14 +54,17 @@ export function openDatabase(userID: string): Promise { }); } +async function getDBTransactionStore(userID:string) { + const db = await openDatabase(userID); + const transaction = db.transaction(postStoreName, "readwrite"); + const store = transaction.objectStore(postStoreName); + return {db, transaction, store} +} export async function addData(userID: string, data: any): Promise { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); - + const {db, transaction, store} = await getDBTransactionStore(userID); const addRequest = store.add({ post_timestamp: data.post_timestamp, data: data }); addRequest.onsuccess = (e: Event) => { @@ -76,12 +83,9 @@ export async function addData(userID: string, data: any): Promise { export async function deleteData(userID: string, postID: string) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const {db, transaction, store} = await getDBTransactionStore(userID); const index = store.index("postIDIndex"); - const getRequest = index.getKey(postID); getRequest.onerror = e => console.log((e.target as IDBRequest).error) @@ -104,9 +108,7 @@ export async function deleteData(userID: string, postID: string) { export async function clearData(userID: string) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const {db, transaction, store} = await getDBTransactionStore(userID); const clearRequest = store.clear(); clearRequest.onsuccess = (e: Event) => { @@ -126,9 +128,7 @@ export async function clearData(userID: string) { export async function addDataArray(userID: string, array: any[]): Promise { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const {db, transaction, store} = await getDBTransactionStore(userID); let count = 0; @@ -161,13 +161,12 @@ export async function addDataArray(userID: string, array: any[]): Promise export async function checkPostIds(userID: string, post_ids: string[]) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const {db, transaction, store} = await getDBTransactionStore(userID); + const index = store.index("postIDIndex"); transaction.oncomplete = () => { - console.log("Transaction completed successfully"); + // console.log("Transaction completed successfully"); db.close(); }; @@ -214,13 +213,12 @@ export async function checkPostIds(userID: string, post_ids: string[]) { export async function mergeDataArray(userID: string, array: any[]): Promise { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const {db, transaction, store} = await getDBTransactionStore(userID); + const index = store.index("postIDIndex"); transaction.oncomplete = () => { - console.log("Transaction completed successfully"); + // console.log("Transaction completed successfully"); db.close(); }; @@ -266,46 +264,35 @@ export async function mergeDataArray(userID: string, array: any[]): Promise { + +} + + export async function getData(userID: string, lowerID: Date, upperID: Date): Promise { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const { store } = await getDBTransactionStore(userID); + const keyRangeValue = IDBKeyRange.bound(lowerID, upperID); + const index = store.index("datetimeIndex"); return new Promise((resolve, reject) => { - const keyRangeValue = IDBKeyRange.bound(lowerID, upperID); + const getAllRequest = index.getAll(keyRangeValue); - const records: any[] = []; - - const index = store.index("datetimeIndex"); - - - const cursorRequest = index.openCursor(keyRangeValue); - - cursorRequest.onsuccess = (event: Event) => { - const cursor = (event.target as IDBRequest).result as IDBCursorWithValue; - if (cursor) { - records.push(cursor.value.data); // Collect the record - cursor.continue(); // Move to the next item in the range - } else { - // No more entries in the range - resolve(records); - } + getAllRequest.onsuccess = () => { + const records = getAllRequest.result.map((item: any) => item.data); + resolve(records); }; - cursorRequest.onerror = (event: Event) => { - // Use a type assertion to access the specific properties of IDBRequest error event - const errorEvent = event as IDBRequestEvent; - console.error('Transaction failed:', errorEvent.target.error?.message); - reject(errorEvent.target.error); // Reject the promise if there's an error + getAllRequest.onerror = () => { + console.error('Transaction failed:', getAllRequest.error?.message); + reject(getAllRequest.error); }; }); } + export async function getAllData(userID: string): Promise { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const {store} = await getDBTransactionStore(userID); return new Promise((resolve, reject) => { const getRequest = store.getAll(); @@ -331,9 +318,8 @@ export async function getAllData(userID: string): Promise { } export async function getAllIds(userID: string): Promise { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const {store} = await getDBTransactionStore(userID); + const index = store.index("postIDIndex"); let keys: string[] = []; @@ -357,9 +343,7 @@ export async function getAllIds(userID: string): Promise { } export async function getPostsByIds(userID:string, postIDs:string[]) { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const {store} = await getDBTransactionStore(userID); const index = store.index("postIDIndex"); let posts = []; diff --git a/src/main.ts b/src/main.ts index a57d270..c7f0aa6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,7 @@ -import { getData, addData, addDataArray, clearData, deleteData, mergeDataArray, getAllData, checkPostIds, getAllIds, getPostsByIds} from "./db.js" +import { getData, addData, addDataArray, clearData, deleteData, mergeDataArray, getAllData, checkPostIds, getAllIds, getPostsByIds } from "./db.js" declare let WebTorrent: any; @@ -31,6 +31,56 @@ function uuidv4() { ); } +function uuidToBytes(uuid: string): Uint8Array { + return new Uint8Array(uuid.match(/[a-fA-F0-9]{2}/g)!.map((hex) => parseInt(hex, 16))); +} + +// Base58 character set +const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; +// Base58 encoding +// Base58 encoding +function encodeBase58(buffer: Uint8Array): string { + let carry; + const digits = [0]; + + for (const byte of buffer) { + carry = byte; + for (let i = 0; i < digits.length; i++) { + carry += digits[i] << 8; + digits[i] = carry % 58; + carry = Math.floor(carry / 58); + } + while (carry > 0) { + digits.push(carry % 58); + carry = Math.floor(carry / 58); + } + } + + let result = ''; + for (const digit of digits.reverse()) { + result += BASE58_ALPHABET[digit]; + } + + // Handle leading zero bytes + for (const byte of buffer) { + if (byte === 0x00) { + result = BASE58_ALPHABET[0] + result; + } else { + break; + } + } + + return result; +} + +// Convert UUID v4 to Base58 +function uuidToBase58(uuid: string): string { + const bytes = uuidToBytes(uuid); + return encodeBase58(bytes); +} + + + let logLines: string[] = []; let logLength = 10; @@ -101,7 +151,7 @@ window.addEventListener('scroll', () => { console.log('Scrolled to the bottom!'); console.log(scrollPoint, totalPageHeight); } - + }); @@ -123,23 +173,36 @@ window.addEventListener('scroll', () => { // } // } -function arrayBufferToBase64( buffer:ArrayBuffer ) { - var binary = ''; - var bytes = new Uint8Array( buffer ); - var len = bytes.byteLength; - for (var i = 0; i < len; i++) { - binary += String.fromCharCode( bytes[ i ] ); - } - return window.btoa( binary ); +async function bytesToBase64DataUrl(bytes: Uint8Array, type = "application/octet-stream") { + return await new Promise((resolve, reject) => { + const reader = Object.assign(new FileReader(), { + onload: () => resolve(reader.result), + onerror: () => reject(reader.error), + }); + reader.readAsDataURL(new File([bytes], "", { type })); + }); } -function base64ToArrayBuffer(base64:string) { - var binaryString = atob(base64); - var bytes = new Uint8Array(binaryString.length); - for (var i = 0; i < binaryString.length; i++) { - bytes[i] = binaryString.charCodeAt(i); - } - return bytes.buffer; +async function arrayBufferToBase64(buffer: ArrayBuffer) { + var bytes = new Uint8Array(buffer); + return (await bytesToBase64DataUrl(bytes) as string).replace("data:application/octet-stream;base64,", ""); +} + +// function base64ToArrayBuffer(base64: string) { +// var binaryString = atob(base64); +// var bytes = new Uint8Array(binaryString.length); +// for (var i = 0; i < binaryString.length; i++) { +// bytes[i] = binaryString.charCodeAt(i); +// } +// return bytes.buffer; +// } + +async function base64ToArrayBuffer(base64String: string) { + let response = await fetch("data:application/octet-stream;base64," + base64String); + let arrayBuffer = await response.arrayBuffer(); + return arrayBuffer; + // let buffer = new Uint8Array(arrayBuffer); + // return buffer; } class wsConnection { @@ -154,7 +217,7 @@ class wsConnection { messageHandlers: Map void> = new Map(); peerMessageHandlers: Map void> = new Map(); - + send(message: any) { let json = "" try { @@ -162,13 +225,26 @@ class wsConnection { } catch (e) { console.log(e, "wsConnection send: Couldn't serialize message", message); } - log(`ws->${json.slice(0,240)}`) + // log(`ws->${json.slice(0, 240)}`) this.websocket!.send(json); } helloResponseHandler(data: any) { - for (let [userID, peerIDs] of Object.entries(data.userPeers)) { + + let users = []; + try { + let currentUserPeers = data.userPeers[app.router.userID]; + users.push([app.router.userID, data.userPeers[app.router.userID]]); + delete data.userPeers[app.router.userID]; + } catch (e) { + console.log('helloResponseHandler', e); + } + + users = [...users, ...Object.entries(data.userPeers)]; + log(`Network: got ${users.length} users from bootstrap peer. ${users.join(',')}`) + + for (let [userID, peerIDs] of users) { this.peers.set(userID, [...Object.keys(peerIDs as any)]); for (let peerID of [...Object.keys(peerIDs as any)]) { @@ -176,11 +252,12 @@ class wsConnection { continue; } + log(`Network: Requesting post IDs for user ${userID} from peer ${peerID}`); this.send({ - type:"peer_message", - from:this.peerID, - to:peerID, - message:{type:"get_post_ids_for_user", user_id:userID} + type: "peer_message", + from: this.peerID, + to: peerID, + message: { type: "get_post_ids_for_user", user_id: userID } }) } } @@ -193,8 +270,8 @@ class wsConnection { // log(`getPostsForUserResponse: ${data}`) let message = data.message; - console.log(`getPostIdsForUserResponseHandler Got ${message.post_ids.length} from peer ${data.from}`); - + log(`Network: got ${message.post_ids.length} post IDs for user ${data.message.user_id} from peer ${data.from}`); + console.log(`Checking post IDs...`); let postIds = await checkPostIds(message.user_id, data.message.post_ids); @@ -203,18 +280,36 @@ class wsConnection { return; } + log(`Network: requesting ${postIds.length} posts for user ${message.user_id} from peer ${data.from}`) let responseMessage = { type: "peer_message", from: app.peerID, to: data.from, message: { type: "get_posts_for_user", post_ids: postIds, user_id: message.user_id } } this.send(responseMessage); } - + + // static async compressArrayBuffer(data: ArrayBuffer): Promise { + // const compressionStream = new CompressionStream('gzip'); // You can also use 'deflate', 'deflate-raw', etc. + + // const compressedStream = new Response( + // new Blob([data]).stream().pipeThrough(compressionStream) + // ); + + // const compressedArrayBuffer = await compressedStream.arrayBuffer(); + + // return compressedArrayBuffer; + // } async getPostIdsForUserHandler(data: any) { let message = data.message; - let postIds = await getAllIds(message.user_id) ?? []; + let postIds = await getAllIds(message.user_id) ?? []; + if (postIds.length === 0) { + log(`Network: I know about user ${message.user_id} but I have 0 posts, so I'm not sending any to to peer ${data.from}`); + return; + } + log(`Network: Sending ${postIds.length} post Ids for user ${message.user_id} to peer ${data.from}`) + let responseMessage = { type: "peer_message", from: app.peerID, to: data.from, message: { type: "get_post_ids_for_user_response", post_ids: postIds, user_id: message.user_id } } - this.send(responseMessage) + this.send(responseMessage); } // Send posts to peer @@ -222,43 +317,65 @@ class wsConnection { let message = data.message; let posts = await getPostsByIds(message.user_id, message.post_ids) ?? []; + log(`Network: Sending ${posts.length} posts for user ${message.user_id} to peer ${data.from}`); + + app.timerStart(); let output = []; for (let post of posts) { - let newPost = (post as any).data; if (newPost.image_data) { - newPost.image_data = arrayBufferToBase64(newPost.image_data) + let newPost = (post as any).data; + + if (newPost.image_data) { + // let compressedData = await wsConnection.compressArrayBuffer(newPost.image_data); + // console.log((newPost.image_data.byteLength - compressedData.byteLength) / 1024 / 1024); + newPost.image_data = await arrayBufferToBase64(newPost.image_data) + } - + + // let megs = JSON.stringify(newPost).length/1024/1024; + // console.log(`getPostsForUserHandler id:${newPost.post_id} post length:${megs}`); output.push(newPost); } - + // posts = posts.map((post:any)=>{let newPost = post.data; if (newPost.image_data){newPost.image_data = arraybufferto};return newPost}); // posts = posts.map((post:any)=>{}) let responseMessage = { type: "peer_message", from: app.peerID, to: data.from, message: { type: "get_posts_for_user_response", posts: output, user_id: message.user_id } } this.send(responseMessage) + let sendTime = app.timerDelta(); + + log(`send took: ${sendTime.toFixed(2)}ms`); + } // Got posts from peer - async getPostsForUserReponseHandler(data: any) { + async getPostsForUserReponseHandler(data: any) { + app.timerStart(); let message = data.message; + console.log(`Network: got ${message.posts.length} posts for user ${message.user_id} from peer ${data.from}`); console.log(`getPostsForUserResponseHandler Got ${message.posts.length} from peer ${data.from}`); for (let post of message.posts) { + if (message.user_id === app.userID) { + post.author_id = app.userID; + } post.post_timestamp = new Date(post.post_timestamp); if (post.image_data) { - post.image_data = base64ToArrayBuffer(post.image_data); + post.image_data = await base64ToArrayBuffer(post.image_data); } } console.log(`Merging same user peer posts...`) - await mergeDataArray(message.user_id, data.message.posts) + await mergeDataArray(message.user_id, data.message.posts); + + let receiveTime = app.timerDelta(); + + log(`Receive took: ${receiveTime.toFixed(2)}ms`); - if (message.user_id === this.userID) { - app.posts = await app.loadPosts(this.userID) ?? []; - app.render(app.posts); + if (message.user_id === app.router.userID) { + app.render(); } } async peerMessageHandler(data: any) { - log(`peerMessageHandler ${data}`) + // log(`peerMessageHandler ${JSON.stringify(data)}`) let peerMessageType = data.message.type; @@ -287,14 +404,16 @@ class wsConnection { return; } - this.websocket.onopen = (event) => { + this.websocket.onopen = async (event) => { log("ws:connected"); - this.send({type:"hello", user_id: this.userID, peer_id:this.peerID}); + let knownUsers = [...(await indexedDB.databases())].map((db) => db.name?.replace('user_', '')); + console.log('Network: Sending known users', knownUsers); + this.send({ type: "hello", user_id: this.userID, peer_id: this.peerID, known_users: knownUsers }); this.websocketPingInterval = window.setInterval(() => { if (!navigator.onLine) { return; } - this.send({type:"ping", peer_id: this.peerID}); + this.send({ type: "ping", peer_id: this.peerID }); }, 10_000) }; @@ -306,7 +425,7 @@ class wsConnection { }; this.websocket.onmessage = (event) => { - log('ws:<-' + event.data.slice(0,240)); + // log('ws:<-' + event.data.slice(0, 240)); let data = JSON.parse(event.data); @@ -361,6 +480,8 @@ class App { userID: string = ''; peerID: string = ''; posts: Post[] = []; + isHeadless: boolean = false; + showLog: boolean = false; initMarkdown() { const renderer = new marked.Renderer(); @@ -511,19 +632,19 @@ class App { }); } - addPost(userID: string, postText: string, imageData?: ArrayBuffer) { + addPost(userID: string, postText: string, mediaData?: ArrayBuffer, mediaType?: "image/png" | "image/gif" | "image/jpg" | "video/mp4") { if ((typeof postText !== "string") || postText.length === 0) { log("Not posting an empty string...") return; } - let post = new Post(this.username, userID, postText, new Date(), imageData); + let post = new Post(this.username, userID, postText, new Date(), mediaData); this.posts.push(post); // localStorage.setItem(key, JSON.stringify(posts)); addData(userID, post) - this.render(this.posts); + this.render(); } @@ -551,11 +672,30 @@ class App { return id; } + animals = ['shrew', 'jerboa', 'lemur', 'weasel', 'possum', 'possum', 'marmoset', 'planigale', 'mole', 'narwhal']; + adjectives = ['snazzy', 'whimsical', 'jazzy', 'bonkers', 'wobbly', 'spiffy', 'chirpy', 'zesty', 'bubbly', 'perky', 'sassy']; + + hashUserIdToIndices() { + let indices = []; + for (let char of this.userID) { + if (char !== '0' && char !== '-') { + indices.push(parseInt(char, 16)); + if (indices.length == 2) { + break; + } + } + } + return [indices[0], indices[1]]; + } + getUsername() { let username = localStorage.getItem("dandelion_username"); - if (!username) { - username = "not_set" + if (!username || username === "not_set") { + let [one, two] = this.hashUserIdToIndices(); + let adjective = this.adjectives[one % this.adjectives.length] + let animal = this.animals[two % this.animals.length] + username = `${adjective}_${animal}` localStorage.setItem("dandelion_username", username); } @@ -592,8 +732,7 @@ class App { window.addEventListener('online', async () => { log("online") connection.connect(); - this.posts = await this.loadPosts(this.userID) ?? []; - this.render(this.posts); + this.render(); }); log(`Online status: ${navigator.onLine ? "online" : "offline"}`) @@ -650,14 +789,32 @@ class App { let clearPostsButton = document.getElementById("clear_posts") as HTMLButtonElement; let updateApp = document.getElementById("update_app") as HTMLButtonElement; let ddlnLogoButton = document.getElementById('ddln_logo_button') as HTMLDivElement; - // let addP = document.getElementById('button_add_pic') as HTMLDivElement; + // let addPic = document.getElementById('button_add_pic') as HTMLDivElement; + let filePickerLabel = document.getElementById('file_input_label'); + let filePicker = document.getElementById('file_input') as HTMLInputElement; + let toggleDark = document.getElementById('toggle_dark') as HTMLButtonElement; + + toggleDark.addEventListener('click', () => { + document.documentElement.style.setProperty('--main-bg-color', 'white'); + document.documentElement.style.setProperty('--main-fg-color', 'black'); + }) + filePicker?.addEventListener('change', async (event: any) => { + for (let file of filePicker.files as any) { + let buffer = await file.arrayBuffer(); + let type = + this.addPost(this.userID, 'image...', buffer); + } + }); + + filePickerLabel?.addEventListener('click', () => { + console.log("Add pic...") + }) - let usernameField = document.getElementById('username'); - usernameField?.addEventListener('input', (event:any)=>{ + usernameField?.addEventListener('input', (event: any) => { this.username = event.target.innerText; localStorage.setItem("dandelion_username", this.username); }) @@ -678,12 +835,11 @@ class App { clearData(userID); // posts = posts.reverse(); addDataArray(userID, imported_posts); - posts = await this.loadPosts(userID) ?? []; - this.render(posts); + this.render(); }); - clearPostsButton.addEventListener('click', () => { clearData(userID); posts = []; this.render(posts) }); + clearPostsButton.addEventListener('click', () => { clearData(userID); posts = []; this.render() }); let postButton = document.getElementById("button_post") as HTMLButtonElement; @@ -693,12 +849,12 @@ class App { throw new Error(); } - postText.addEventListener('paste', async (e)=>{ + postText.addEventListener('paste', async (e) => { const dataTransfer = e.clipboardData - const file = dataTransfer!.files[ 0 ]; + const file = dataTransfer!.files[0]; let buffer = await file.arrayBuffer(); - let type = - this.addPost(this.userID, 'image...', buffer); + let type = + this.addPost(this.userID, 'image...', buffer); }); postButton.addEventListener("click", () => { @@ -719,10 +875,16 @@ class App { ddlnLogoButton.addEventListener('click', () => { infoElement.style.display == 'none' ? infoElement.style.display = 'block' : infoElement.style.display = 'none'; }); } - async loadPosts(userID: string) { + async loadPosts(userID: string, postID?: string) { this.timerStart(); - let posts: any = await getData(userID, new Date(2022, 8), new Date()); + let posts: Post[] = []; + + // if (postID) { + // posts = await gePostForUser(userID, postID); + // } + + posts = await getData(userID, new Date(2022, 8), new Date()); if (posts.length > 0) { log(`Loaded ${posts.length} posts in ${this.timerDelta().toFixed(2)}ms`); @@ -736,27 +898,47 @@ class App { // return await getData(userID, new Date(2022, 8), new Date()); } - async main() { - let urlParams = (new URL(window.location.href)).searchParams; - let connection_userID = urlParams.get('connect'); - - let registration = undefined; - // if (urlParams.get("sw") === "true") { - registration = await this.registerServiceWorker(); - // } - - if (connection_userID) { - console.log('connect', connection_userID); - localStorage.setItem("dandelion_id", connection_userID); + async purgeEmptyUsers() { + let knownUsers = [...(await indexedDB.databases())].map((db) => db.name?.replace('user_', '')); + if (!knownUsers) { + return; } - this.username = this.getUsername(); - document.getElementById('username')!.innerText = this.username; + for (let userID of knownUsers as string[]) { + let ids = await getAllIds(userID); + if (ids.length === 0) { + console.log(`Purging user ${userID}`); + indexedDB.deleteDatabase(`user_${userID}`); + } + + console.log(`https://ddln.app/user/${userID}`); + } + + } + + async main() { + this.isHeadless = /\bHeadlessChrome\//.test(navigator.userAgent) let userID = this.getUserID(); let peerID = this.getPeerID(); this.userID = userID; this.peerID = peerID; - this.initButtons(userID, this.posts, registration); + this.getRoute(); + + if (this.router.route === App.Route.CONNECT) { + console.log('connect', this.router.userID); + localStorage.setItem("dandelion_id", this.router.userID); + } + + let urlParams = (new URL(window.location.href)).searchParams; + let connection_userID = urlParams.get('connect'); + + let registration = undefined; + + if (urlParams.has('log')) { + document.getElementById('info')!.style.display = "block"; + this.showLog = true; + } + let time = 0; let delta = 0; @@ -776,20 +958,25 @@ class App { // console.log(code); // registration.active.postMessage({type:"updateMain", code:code}); - this.posts = await this.loadPosts(userID) ?? []; + // this.posts = await this.loadPosts(userID) ?? []; // debugger; - this.timerStart(); - this.render(this.posts); // , (postID:string)=>{this.deletePost(userID, postID)} - let renderTime = this.timerDelta(); - - log(`render took: ${renderTime.toFixed(2)}ms`); + await this.render(); // , (postID:string)=>{this.deletePost(userID, postID)} if ((performance as any)?.memory) { log(`memory used: ${((performance as any).memory.usedJSHeapSize / 1024 / 1024).toFixed(2)}Mb`) } - let connectURL = `https://${document.location.hostname}?connect=${this.userID}`; + // if (urlParams.get("sw") === "true") { + registration = await this.registerServiceWorker(); + // } + + this.username = this.getUsername(); + document.getElementById('username')!.innerText = this.username; + + this.initButtons(userID, this.posts, registration); + + let connectURL = `https://${document.location.hostname}/connect/${this.userID}`; document.getElementById('connectURL')!.innerHTML = `connect`; let qrcode = await new QRCode(document.getElementById('qrcode'), { @@ -801,11 +988,14 @@ class App { correctLevel: QRCode.CorrectLevel.H }); - - let qrcodeImage:HTMLImageElement = document.querySelector('#qrcode > img') as HTMLImageElement; - qrcodeImage.classList.add('qrcode_image'); - log(`user:${userID} peer:${peerID}`); + (document.querySelector('#qrcode > img') as HTMLImageElement).classList.add('qrcode_image'); + (document.querySelector('#qrcode > canvas') as HTMLImageElement).classList.add('qrcode_image'); + + log(`username:${this.username} user:${userID} peer:${peerID}`); + + await this.purgeEmptyUsers(); + let websocket = new wsConnection(userID, peerID); window.addEventListener('beforeunload', () => { websocket.disconnect() }) this.initOffline(websocket); @@ -828,7 +1018,52 @@ class App { // }) } - render(posts: Post[]) { + + // keep a map of posts to dom nodes. + // on re-render + // posts that are not in our list that we need at add + // posts that are in our list that we need to remove + + // postsSet = new Set(); + + async render() { + if (this.isHeadless) { + console.log('Headless so skipping render...'); + return; + } + this.timerStart(); + + let posts = []; + switch (this.router.route) { + case App.Route.HOME: + case App.Route.CONNECT: { + posts = await this.loadPosts(this.userID) ?? []; + break; + } + case App.Route.USER: { + posts = await this.loadPosts(this.router.userID) ?? []; + break; + } + case App.Route.POST: { + posts = await this.loadPosts(this.router.userID, this.router.postID) ?? []; + break; + } + default: { + console.log("Render: got a route I didn't understand. Rendering HOME:", this.router.route); + posts = await this.loadPosts(this.userID) ?? []; + break; + } + + } + + // let newPostsSet = new Set(posts.map(post=>post.post_id)); + // let newPosts = (newPostsSet as any).difference(this.postsSet); + // // let removedPosts = (this.postsSet as any).difference(newPosts); + // let keepPosts = (this.postsSet as any).intersection(newPostsSet); + + // let renderPosts = keepPosts.union(newPosts); + + const fragment = document.createDocumentFragment(); let contentDiv = document.getElementById("content"); if (!contentDiv) { @@ -839,8 +1074,9 @@ class App { for (let i = posts.length - 1; i >= 0; i--) { let postData = posts[i]; + // this.postsSet.add(postData); - let post = this.renderPost(postData, posts); + let post = this.renderPost(postData); if (post) { fragment.appendChild(post); @@ -858,15 +1094,23 @@ class App { contentDiv.appendChild(fragment); + let renderTime = this.timerDelta(); + + log(`render took: ${renderTime.toFixed(2)}ms`); + + if ((performance as any)?.memory) { + log(`memory used: ${((performance as any).memory.usedJSHeapSize / 1024 / 1024).toFixed(2)}Mb`) + } + } async deletePost(userID: string, postID: string) { deleteData(userID, postID) - this.posts = await this.loadPosts(userID) ?? []; - this.render(this.posts); + + this.render(); } - renderPost(post: Post, posts: Post[]) { + renderPost(post: Post) { if (!(post.hasOwnProperty("text"))) { throw new Error("Post is malformed!"); } @@ -875,23 +1119,41 @@ class App { let timestamp = `${post.post_timestamp.toLocaleTimeString()} ยท ${post.post_timestamp.toLocaleDateString()}`; let deleteButton = document.createElement('button'); deleteButton.innerText = 'delete'; + deleteButton.onclick = () => { this.deletePost(post.author_id, post.post_id) }; + let editButton = document.createElement('button'); editButton.innerText = 'edit'; - deleteButton.onclick = () => { this.deletePost(this.userID, post.post_id) }; + let shareButton = document.createElement('button'); shareButton.innerText = 'share'; + shareButton.onclick = async () => { + let shareUrl = `https://${document.location.hostname}/user/${post.author_id}/post/${post.post_id}`; + + await navigator.clipboard.writeText(shareUrl) + }; + + let ownPost = post.author_id === this.userID; let postTemplate = `

-
- @${post.author} - - ${post.post_timestamp.toLocaleDateString()} - -
-
${marked.parse(post.text)}
-
` +
+ @${post.author} - + ${post.post_timestamp.toLocaleDateString()} + + ${ownPost ? `` : ''} + ${ownPost ? `` : ''} + +
+
${marked.parse(post.text)}
+ ` containerDiv.innerHTML = postTemplate; - containerDiv.querySelector('#deleteButton')?.appendChild(deleteButton); - containerDiv.querySelector('#editButton')?.appendChild(editButton); + + if (ownPost) { + containerDiv.querySelector('#deleteButton')?.appendChild(deleteButton); + containerDiv.querySelector('#editButton')?.appendChild(editButton); + } + + + containerDiv.querySelector('#shareButton')?.appendChild(shareButton); if (!("image_data" in post && post.image_data)) { // containerDiv.appendChild(timestampDiv); @@ -900,6 +1162,7 @@ class App { } let image = document.createElement("img"); + image.title = `${(post.image_data.byteLength / 1024 / 1024).toFixed(2)}MBytes`; // const blob = new Blob([post.image_data as ArrayBuffer], { type: 'image/png' }); const blob = new Blob([post.image_data as ArrayBuffer]); const url = URL.createObjectURL(blob); @@ -907,12 +1170,10 @@ class App { URL.revokeObjectURL(url); }; - - - image.src = url; // image.src = image.src = "data:image/png;base64," + post.image; image.className = "postImage"; + image.onclick = () => { App.maximizeElement(image) }; containerDiv.appendChild(image); // containerDiv.appendChild(timestampDiv); @@ -920,8 +1181,72 @@ class App { return containerDiv; } + static maximizeElement(element: HTMLImageElement) { + element.style.transform = "scale(2.0)" + } + + router = { + route: App.Route.HOME, + userID: '', + postID: '', + mediaID: '' + } + + getRoute() { + app.router.userID = this.userID; + let path = document.location.pathname; + console.log(">>>>>>>>>>>>>>>>>>>>>>>>>", path); + + const regex = "(user/([a-zA-Z0-9\-]+)/?(post/([a-zA-Z0-9\-]+)?/?)?(media/([0-9]+)?)?)|(connect/([a-zA-Z0-9\-]+))"; + + const match = path.match(new RegExp(regex)); + + if (match) { + if (match[8]) { // Check for the connect route + this.router.userID = match[8]; + this.router.route = App.Route.CONNECT; + } else { + + this.router.userID = match[2]; + this.router.postID = match[4]; + this.router.mediaID = match[6]; + + if (this.router.mediaID) { + this.router.route = App.Route.MEDIA; + } else if (this.router.postID) { + this.router.route = App.Route.POST; + } else { + this.router.route = App.Route.USER; + } + } + } + + console.log(">>>>>>>>>>>>>", this.router, App.Route[this.router.route]); + + // user = /user/ + // post = /user//post/ + // media = /user//post//media/ + // group = /group/ID/post/ + // hashtag = /hashtag/ -- maybe only hastags in groups + // home = / + + } + } +namespace App { + export enum Route { + USER, + POST, + MEDIA, + GROUP, + HOME, + CONNECT, + }; +} + + + let app = new App(); window.addEventListener("load", app.main.bind(app)); diff --git a/src/sw.ts b/src/sw.ts index 55d600d..6307850 100644 --- a/src/sw.ts +++ b/src/sw.ts @@ -1,14 +1,15 @@ +const debugLog = false; // Establish a cache name const cacheName = "dandelion_cache_v1"; const contentToCache = [ - '/index.html', - '/main.css', - '/main.js', - 'lib//marked.min.js', - 'lib/qrcode.min.js', - '/db.js', - '/favicon.ico' + '/static/index.html', + '/static/main.css', + '/static/main.js', + '/static/lib/marked.min.js', + '/static/lib/qrcode.min.js', + '/static/db.js', + '/static/favicon.ico' ]; self.addEventListener("install", (e: any) => { @@ -19,55 +20,126 @@ self.addEventListener("install", (e: any) => { "[Service Worker] Caching all: app shell and content", contentToCache ); - await cache.addAll(contentToCache); + + try { + await cache.addAll(contentToCache); + } catch (e) { + debugLog ? console.log(e) : null; + } })() ); }); -async function responder(event: any) { - console.log('Fetching', event.request.url); - let response = await fetch(event.request); +async function staleWhileRevalidate(event: any) { - if (!response) { - console.log('Fetch failed, falling back to cache', event.request.url); - let cacheMatch = await caches.match(event.request); - if (!cacheMatch) { - // DUnno what to return here! + let cache = await caches.open(cacheName); + + let response = await cache.match(event.request); + + if (response) { + debugLog ? console.log('Service Worker: Cache hit', event.request.url) : null; + } + + const fetchPromise = (async () => { + debugLog ? console.log('Service Worker: Fetching', event.request.url) : null; + + let networkResponse = null; + try { + networkResponse = await fetch(event.request); + } catch (e) { + debugLog ? console.log('Service Worker: Failed to fetch', e) : null; + + return new Response('Network error occurred', { + status: 404, + statusText: 'Cache miss and fetch failed', + headers: { 'Content-Type': 'text/plain' } + }); } - return cacheMatch; - } - if (response.status === 206) { - console.log('Not caching partial content'); - return response; - } + debugLog ? console.log('Service Worker: Updating cache', event.request.url) : null; - console.log('Fetch successful, updating cache'); - const cache = await caches.open(cacheName); - try { - cache.put(event.request, response.clone()).catch((error)=>console.log('failed to cache', event.request, error)); - } catch (e) { - console.log('failed to cache', event.request) - } - return response; + try { + await cache.put(event.request, networkResponse.clone()); + } catch (e) { + debugLog ? console.log('Service Worker: failed to update cache', event.request.url, e) : null; + + } + + debugLog ? console.log('Service Worker: Returning networkResponse', event.request.url) : null; + return networkResponse; + })(); + + + debugLog ? console.log('Service Worker: Returning return response || fetchPromise', event.request.url) : null; + return response || fetchPromise; + + // if (networkResponse) { + // cache.put(event.request, networkResponse.clone()) + // return networkResponse; + // } + + + + // caches.open(cacheName) + // .then(function (cache) { + // return cache.match(event.request) + // .then(function (response) { + // var fetchPromise = fetch(event.request) + // .then(function (networkResponse) { + // cache.put(event.request, networkResponse.clone()); + // return networkResponse; + // }); + // return response || fetchPromise; + // }); + // }) } +// async function responder(event: any) { +// debugLog ? console.log('Fetching', event.request.url) : null; + +// let response = await fetch(event.request); + +// if (!response) { +// debugLog ? console.log('Fetch failed, falling back to cache', event.request.url) : null; +// let cacheMatch = await caches.match(event.request); +// if (!cacheMatch) { +// // DUnno what to return here! +// } +// return cacheMatch; +// } + +// if (response.status === 206) { +// debugLog ? console.log('Not caching partial content') : null; +// return response; +// } + +// debugLog ? console.log('Fetch successful, updating cache', event.request.url) : null; +// const cache = await caches.open(cacheName); +// try { +// cache.put(event.request, response.clone()).catch((error) => debugLog ? console.log('failed to cache', event.request, error)) : null; +// } catch (e) { +// console.log('failed to cache', event.request) +// } +// return response; +// } + self.addEventListener('fetch', function (event: any) { - event.respondWith(responder(event)); + event.respondWith(staleWhileRevalidate(event)); + // event.respondWith(responder(event)); }); addEventListener("message", async (e) => { - console.log(`Message received:`, e.data); + debugLog ? console.log(`Message received:`, e.data) : null; switch (e.data.type) { case "update_app": const cache = await caches.open(cacheName); - console.log(`[Service Worker] Caching resources`); + debugLog ? console.log(`[Service Worker] Caching resources`) : null; // cache.put("/main.js", new Response()); for (let item of contentToCache) { - cache.delete(item); + cache.delete(item); } await cache.addAll(contentToCache); diff --git a/static/app.webmanifest b/static/app.webmanifest new file mode 100644 index 0000000..2fa924b --- /dev/null +++ b/static/app.webmanifest @@ -0,0 +1,42 @@ +{ + "name": "ddln", + "short_name": "ddln", + "start_url": "/", + "display": "standalone", + "display_override": [ + "window-controls-overlay", + "standalone" + ], + "id": "b1dbe643-36fc-4419-9448-80f32a1baa1a", + "background_color": "#000000", + "theme_color": "#000000", + "icons": [ + { + "src": "/static/icons/dandelion_512x512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "screenshots": [ + { + "src": "/static/images/screenshot1.jpg", + "sizes": "1280x720", + "type": "image/png", + "form_factor": "wide", + "label": "Dandelion desktop" + }, + { + "src": "/static/images/screenshot2.jpg", + "sizes": "720x1280", + "type": "image/png", + "form_factor": "narrow", + "label": "Dandelion mobile" + } + ], + "protocol_handlers": [ + { + "protocol": "web+ddln", + "url": "/%s" + } + ] +} \ No newline at end of file diff --git a/bookerly.woff2 b/static/bookerly.woff2 similarity index 100% rename from bookerly.woff2 rename to static/bookerly.woff2 diff --git a/db.js b/static/db.js similarity index 73% rename from db.js rename to static/db.js index d821f3d..fb090de 100644 --- a/db.js +++ b/static/db.js @@ -7,22 +7,23 @@ const postStoreName = "posts"; let keyBase = "dandelion_posts_v1_"; let key = ""; +let version = 1; +function upgrade_0to1(db) { + let store = db.createObjectStore(postStoreName, { keyPath: "id", autoIncrement: true }); + store.createIndex("datetimeIndex", "post_timestamp", { unique: false }); + store.createIndex("postIDIndex", "data.post_id", { unique: true }); +} export function openDatabase(userID) { const dbName = `user_${userID}`; return new Promise((resolve, reject) => { - const request = indexedDB.open(dbName, 1); + const request = indexedDB.open(dbName, version); request.onerror = (event) => { - // Use a type assertion to access the specific properties of IDBRequest error event const errorEvent = event; reject(`Database error: ${errorEvent.target.error?.message}`); }; request.onupgradeneeded = (event) => { const db = event.target.result; - if (!db.objectStoreNames.contains(postStoreName)) { - let store = db.createObjectStore(postStoreName, { keyPath: "id", autoIncrement: true }); - store.createIndex("datetimeIndex", "post_timestamp", { unique: false }); - store.createIndex("postIDIndex", "data.post_id", { unique: true }); - } + upgrade_0to1(db); }; request.onsuccess = (event) => { const db = event.target.result; @@ -30,11 +31,15 @@ export function openDatabase(userID) { }; }); } +async function getDBTransactionStore(userID) { + const db = await openDatabase(userID); + const transaction = db.transaction(postStoreName, "readwrite"); + const store = transaction.objectStore(postStoreName); + return { db, transaction, store }; +} export async function addData(userID, data) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const { db, transaction, store } = await getDBTransactionStore(userID); const addRequest = store.add({ post_timestamp: data.post_timestamp, data: data }); addRequest.onsuccess = (e) => { // console.log('Data has been added:', (e.target as IDBRequest).result); @@ -51,9 +56,7 @@ export async function addData(userID, data) { } export async function deleteData(userID, postID) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const { db, transaction, store } = await getDBTransactionStore(userID); const index = store.index("postIDIndex"); const getRequest = index.getKey(postID); getRequest.onerror = e => console.log(e.target.error); @@ -74,9 +77,7 @@ export async function deleteData(userID, postID) { } export async function clearData(userID) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const { db, transaction, store } = await getDBTransactionStore(userID); const clearRequest = store.clear(); clearRequest.onsuccess = (e) => { // console.log('Data has been added:', (e.target as IDBRequest).result); @@ -93,9 +94,7 @@ export async function clearData(userID) { } export async function addDataArray(userID, array) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const { db, transaction, store } = await getDBTransactionStore(userID); let count = 0; array.reverse(); for (let data of array) { @@ -120,12 +119,10 @@ export async function addDataArray(userID, array) { } export async function checkPostIds(userID, post_ids) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const { db, transaction, store } = await getDBTransactionStore(userID); const index = store.index("postIDIndex"); transaction.oncomplete = () => { - console.log("Transaction completed successfully"); + // console.log("Transaction completed successfully"); db.close(); }; transaction.onerror = (event) => { @@ -164,12 +161,10 @@ export async function checkPostIds(userID, post_ids) { } export async function mergeDataArray(userID, array) { try { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readwrite"); - const store = transaction.objectStore(postStoreName); + const { db, transaction, store } = await getDBTransactionStore(userID); const index = store.index("postIDIndex"); transaction.oncomplete = () => { - console.log("Transaction completed successfully"); + // console.log("Transaction completed successfully"); db.close(); }; transaction.onerror = (event) => { @@ -206,38 +201,26 @@ export async function mergeDataArray(userID, array) { console.error("Error in opening database:", error); } } +export async function getPostForUser(userID, postID) { +} export async function getData(userID, lowerID, upperID) { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const { store } = await getDBTransactionStore(userID); + const keyRangeValue = IDBKeyRange.bound(lowerID, upperID); + const index = store.index("datetimeIndex"); return new Promise((resolve, reject) => { - const keyRangeValue = IDBKeyRange.bound(lowerID, upperID); - const records = []; - const index = store.index("datetimeIndex"); - const cursorRequest = index.openCursor(keyRangeValue); - cursorRequest.onsuccess = (event) => { - const cursor = event.target.result; - if (cursor) { - records.push(cursor.value.data); // Collect the record - cursor.continue(); // Move to the next item in the range - } - else { - // No more entries in the range - resolve(records); - } + const getAllRequest = index.getAll(keyRangeValue); + getAllRequest.onsuccess = () => { + const records = getAllRequest.result.map((item) => item.data); + resolve(records); }; - cursorRequest.onerror = (event) => { - // Use a type assertion to access the specific properties of IDBRequest error event - const errorEvent = event; - console.error('Transaction failed:', errorEvent.target.error?.message); - reject(errorEvent.target.error); // Reject the promise if there's an error + getAllRequest.onerror = () => { + console.error('Transaction failed:', getAllRequest.error?.message); + reject(getAllRequest.error); }; }); } export async function getAllData(userID) { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const { store } = await getDBTransactionStore(userID); return new Promise((resolve, reject) => { const getRequest = store.getAll(); getRequest.onsuccess = () => { @@ -260,9 +243,7 @@ export async function getAllData(userID) { }); } export async function getAllIds(userID) { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const { store } = await getDBTransactionStore(userID); const index = store.index("postIDIndex"); let keys = []; return new Promise((resolve, reject) => { @@ -283,9 +264,7 @@ export async function getAllIds(userID) { }); } export async function getPostsByIds(userID, postIDs) { - const db = await openDatabase(userID); - const transaction = db.transaction(postStoreName, "readonly"); - const store = transaction.objectStore(postStoreName); + const { store } = await getDBTransactionStore(userID); const index = store.index("postIDIndex"); let posts = []; for (const postID of postIDs) { diff --git a/static/db.js.map b/static/db.js.map new file mode 100644 index 0000000..096737c --- /dev/null +++ b/static/db.js.map @@ -0,0 +1 @@ +{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/favicon.ico b/static/favicon.ico similarity index 100% rename from favicon.ico rename to static/favicon.ico diff --git a/icons/dandelion_512x512.png b/static/icons/dandelion_512x512.png similarity index 100% rename from icons/dandelion_512x512.png rename to static/icons/dandelion_512x512.png diff --git a/images/lottie_test.json b/static/images/lottie_test.json similarity index 100% rename from images/lottie_test.json rename to static/images/lottie_test.json diff --git a/images/screenshot1.jpg b/static/images/screenshot1.jpg similarity index 100% rename from images/screenshot1.jpg rename to static/images/screenshot1.jpg diff --git a/images/screenshot1.png b/static/images/screenshot1.png similarity index 100% rename from images/screenshot1.png rename to static/images/screenshot1.png diff --git a/images/screenshot2.jpg b/static/images/screenshot2.jpg similarity index 100% rename from images/screenshot2.jpg rename to static/images/screenshot2.jpg diff --git a/images/screenshot2.png b/static/images/screenshot2.png similarity index 100% rename from images/screenshot2.png rename to static/images/screenshot2.png diff --git a/index.html b/static/index.html similarity index 73% rename from index.html rename to static/index.html index f6463bf..92ababd 100644 --- a/index.html +++ b/static/index.html @@ -6,15 +6,15 @@ Dandelion - - - + + + - - + + @@ -23,7 +23,7 @@
-
+
@@ -31,10 +31,11 @@
username:unnamed
-
+ +
@@ -47,13 +48,15 @@ +
-
- +
+ + - +
diff --git a/lib/lottie.min.js b/static/lib/lottie.min.js similarity index 100% rename from lib/lottie.min.js rename to static/lib/lottie.min.js diff --git a/lib/marked.min.js b/static/lib/marked.min.js similarity index 100% rename from lib/marked.min.js rename to static/lib/marked.min.js diff --git a/lib/qrcode.min.js b/static/lib/qrcode.min.js similarity index 100% rename from lib/qrcode.min.js rename to static/lib/qrcode.min.js diff --git a/lib/webtorrent/webtorrent_1_8_0.min.js b/static/lib/webtorrent/webtorrent_1_8_0.min.js similarity index 100% rename from lib/webtorrent/webtorrent_1_8_0.min.js rename to static/lib/webtorrent/webtorrent_1_8_0.min.js diff --git a/main.css b/static/main.css similarity index 68% rename from main.css rename to static/main.css index 761b9b8..7457ab6 100644 --- a/main.css +++ b/static/main.css @@ -1,8 +1,18 @@ +:root { + --main-bg-color: black; + --border-color:rgb(132,136,138); + --edge-color:rgb(60,60,60); + --main-fg-color:rgb(202,208,211); + --highlight-fg-color:rgb(255,255,255); + --link-color:rgb(29, 155, 240); +} + body { + font-family: sans-serif; - color: rgb(202, 208, 211); - background-color: black; - /* Use the font with a fallback */ + color: var(--main-fg-color); + background-color: var(--main-bg-color); + margin:0px; } hr { @@ -12,13 +22,13 @@ hr { .form_field { font-size: medium; font-family: sans-serif; - background-color: rgb(0, 0, 0); - color: rgb(202, 208, 211); + background-color: var(--edge-color); + color: var(--main-fg-color); width: 100%; box-sizing: border-box; padding-left: 5px; padding-right: 5px; - border: 1px solid rgb(132, 136, 138); + border: 1px solid var(--border-color); resize: vertical; border-radius: 20px; } @@ -26,14 +36,14 @@ hr { #textarea_post { font-size: medium; font-family: sans-serif; - background-color: rgb(0, 0, 0); - color: rgb(202, 208, 211); + background-color: var(--main-bg-color); + color: var(--main-fg-color); width: 100%; box-sizing: border-box; padding-left: 30px; padding-right: 30px; padding-top: 10px; - border: 1px solid rgb(132, 136, 138); + border: 1px solid var(--border-color); resize: vertical; border-radius: 40px; } @@ -55,7 +65,7 @@ hr { min-width: 300px; /* Minimum width the content can shrink to */ padding: 20px; - box-shadow: 0 0 5px rgb(60, 60, 60); + box-shadow: 0 0 5px var(--edge-color); text-align: left; overflow-x: hidden; /* Hide horizontal overflow inside the flex container */ @@ -82,7 +92,7 @@ hr { width: 50%; } -.button { +.right { text-align: right; } @@ -95,7 +105,7 @@ hr { } a { - color: rgb(29, 155, 240); + color: var(--link-color); } .logo { @@ -113,18 +123,19 @@ a { cursor: pointer; } -button { - background-color: rgb(0, 0, 0); +button,.button { + font-size:small; + background-color: var(--main-bg-color); border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 5px; padding-bottom: 5px; margin-left: 5px; - color: rgb(255, 255, 255); + color: var(--highlight-fg-color); /* border:solid 1px white; */ - border: 1px solid rgb(132, 136, 138); - color: rgb(202, 208, 211); + border: 1px solid var(--border-color); + color: var(--main-fg-color); cursor: pointer; } @@ -137,6 +148,6 @@ iframe { } .qrcode_image { - background-color: white; + background-color: var(--highlight-fg-color); padding: 10px; } \ No newline at end of file diff --git a/main.js b/static/main.js similarity index 63% rename from main.js rename to static/main.js index 9aff6ee..79efae0 100644 --- a/main.js +++ b/static/main.js @@ -17,6 +17,48 @@ function waitMs(durationMs) { function uuidv4() { return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); } +function uuidToBytes(uuid) { + return new Uint8Array(uuid.match(/[a-fA-F0-9]{2}/g).map((hex) => parseInt(hex, 16))); +} +// Base58 character set +const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; +// Base58 encoding +// Base58 encoding +function encodeBase58(buffer) { + let carry; + const digits = [0]; + for (const byte of buffer) { + carry = byte; + for (let i = 0; i < digits.length; i++) { + carry += digits[i] << 8; + digits[i] = carry % 58; + carry = Math.floor(carry / 58); + } + while (carry > 0) { + digits.push(carry % 58); + carry = Math.floor(carry / 58); + } + } + let result = ''; + for (const digit of digits.reverse()) { + result += BASE58_ALPHABET[digit]; + } + // Handle leading zero bytes + for (const byte of buffer) { + if (byte === 0x00) { + result = BASE58_ALPHABET[0] + result; + } + else { + break; + } + } + return result; +} +// Convert UUID v4 to Base58 +function uuidToBase58(uuid) { + const bytes = uuidToBytes(uuid); + return encodeBase58(bytes); +} let logLines = []; let logLength = 10; function log(message) { @@ -72,22 +114,33 @@ window.addEventListener('scroll', () => { // this.addPosts(newPosts); // } // } -function arrayBufferToBase64(buffer) { - var binary = ''; - var bytes = new Uint8Array(buffer); - var len = bytes.byteLength; - for (var i = 0; i < len; i++) { - binary += String.fromCharCode(bytes[i]); - } - return window.btoa(binary); +async function bytesToBase64DataUrl(bytes, type = "application/octet-stream") { + return await new Promise((resolve, reject) => { + const reader = Object.assign(new FileReader(), { + onload: () => resolve(reader.result), + onerror: () => reject(reader.error), + }); + reader.readAsDataURL(new File([bytes], "", { type })); + }); } -function base64ToArrayBuffer(base64) { - var binaryString = atob(base64); - var bytes = new Uint8Array(binaryString.length); - for (var i = 0; i < binaryString.length; i++) { - bytes[i] = binaryString.charCodeAt(i); - } - return bytes.buffer; +async function arrayBufferToBase64(buffer) { + var bytes = new Uint8Array(buffer); + return (await bytesToBase64DataUrl(bytes)).replace("data:application/octet-stream;base64,", ""); +} +// function base64ToArrayBuffer(base64: string) { +// var binaryString = atob(base64); +// var bytes = new Uint8Array(binaryString.length); +// for (var i = 0; i < binaryString.length; i++) { +// bytes[i] = binaryString.charCodeAt(i); +// } +// return bytes.buffer; +// } +async function base64ToArrayBuffer(base64String) { + let response = await fetch("data:application/octet-stream;base64," + base64String); + let arrayBuffer = await response.arrayBuffer(); + return arrayBuffer; + // let buffer = new Uint8Array(arrayBuffer); + // return buffer; } class wsConnection { send(message) { @@ -98,16 +151,28 @@ class wsConnection { catch (e) { console.log(e, "wsConnection send: Couldn't serialize message", message); } - log(`ws->${json.slice(0, 240)}`); + // log(`ws->${json.slice(0, 240)}`) this.websocket.send(json); } helloResponseHandler(data) { - for (let [userID, peerIDs] of Object.entries(data.userPeers)) { + let users = []; + try { + let currentUserPeers = data.userPeers[app.router.userID]; + users.push([app.router.userID, data.userPeers[app.router.userID]]); + delete data.userPeers[app.router.userID]; + } + catch (e) { + console.log('helloResponseHandler', e); + } + users = [...users, ...Object.entries(data.userPeers)]; + log(`Network: got ${users.length} users from bootstrap peer. ${users.join(',')}`); + for (let [userID, peerIDs] of users) { this.peers.set(userID, [...Object.keys(peerIDs)]); for (let peerID of [...Object.keys(peerIDs)]) { if (peerID === this.peerID) { continue; } + log(`Network: Requesting post IDs for user ${userID} from peer ${peerID}`); this.send({ type: "peer_message", from: this.peerID, @@ -122,19 +187,33 @@ class wsConnection { async getPostIdsForUserResponseHandler(data) { // log(`getPostsForUserResponse: ${data}`) let message = data.message; - console.log(`getPostIdsForUserResponseHandler Got ${message.post_ids.length} from peer ${data.from}`); + log(`Network: got ${message.post_ids.length} post IDs for user ${data.message.user_id} from peer ${data.from}`); console.log(`Checking post IDs...`); let postIds = await checkPostIds(message.user_id, data.message.post_ids); if (postIds.length === 0) { log(`Don't need any posts from peer ${data.from}`); return; } + log(`Network: requesting ${postIds.length} posts for user ${message.user_id} from peer ${data.from}`); let responseMessage = { type: "peer_message", from: app.peerID, to: data.from, message: { type: "get_posts_for_user", post_ids: postIds, user_id: message.user_id } }; this.send(responseMessage); } + // static async compressArrayBuffer(data: ArrayBuffer): Promise { + // const compressionStream = new CompressionStream('gzip'); // You can also use 'deflate', 'deflate-raw', etc. + // const compressedStream = new Response( + // new Blob([data]).stream().pipeThrough(compressionStream) + // ); + // const compressedArrayBuffer = await compressedStream.arrayBuffer(); + // return compressedArrayBuffer; + // } async getPostIdsForUserHandler(data) { let message = data.message; let postIds = await getAllIds(message.user_id) ?? []; + if (postIds.length === 0) { + log(`Network: I know about user ${message.user_id} but I have 0 posts, so I'm not sending any to to peer ${data.from}`); + return; + } + log(`Network: Sending ${postIds.length} post Ids for user ${message.user_id} to peer ${data.from}`); let responseMessage = { type: "peer_message", from: app.peerID, to: data.from, message: { type: "get_post_ids_for_user_response", post_ids: postIds, user_id: message.user_id } }; this.send(responseMessage); } @@ -142,38 +221,52 @@ class wsConnection { async getPostsForUserHandler(data) { let message = data.message; let posts = await getPostsByIds(message.user_id, message.post_ids) ?? []; + log(`Network: Sending ${posts.length} posts for user ${message.user_id} to peer ${data.from}`); + app.timerStart(); let output = []; for (let post of posts) { let newPost = post.data; if (newPost.image_data) { - newPost.image_data = arrayBufferToBase64(newPost.image_data); + // let compressedData = await wsConnection.compressArrayBuffer(newPost.image_data); + // console.log((newPost.image_data.byteLength - compressedData.byteLength) / 1024 / 1024); + newPost.image_data = await arrayBufferToBase64(newPost.image_data); } + // let megs = JSON.stringify(newPost).length/1024/1024; + // console.log(`getPostsForUserHandler id:${newPost.post_id} post length:${megs}`); output.push(newPost); } // posts = posts.map((post:any)=>{let newPost = post.data; if (newPost.image_data){newPost.image_data = arraybufferto};return newPost}); // posts = posts.map((post:any)=>{}) let responseMessage = { type: "peer_message", from: app.peerID, to: data.from, message: { type: "get_posts_for_user_response", posts: output, user_id: message.user_id } }; this.send(responseMessage); + let sendTime = app.timerDelta(); + log(`send took: ${sendTime.toFixed(2)}ms`); } // Got posts from peer async getPostsForUserReponseHandler(data) { + app.timerStart(); let message = data.message; + console.log(`Network: got ${message.posts.length} posts for user ${message.user_id} from peer ${data.from}`); console.log(`getPostsForUserResponseHandler Got ${message.posts.length} from peer ${data.from}`); for (let post of message.posts) { + if (message.user_id === app.userID) { + post.author_id = app.userID; + } post.post_timestamp = new Date(post.post_timestamp); if (post.image_data) { - post.image_data = base64ToArrayBuffer(post.image_data); + post.image_data = await base64ToArrayBuffer(post.image_data); } } console.log(`Merging same user peer posts...`); await mergeDataArray(message.user_id, data.message.posts); - if (message.user_id === this.userID) { - app.posts = await app.loadPosts(this.userID) ?? []; - app.render(app.posts); + let receiveTime = app.timerDelta(); + log(`Receive took: ${receiveTime.toFixed(2)}ms`); + if (message.user_id === app.router.userID) { + app.render(); } } async peerMessageHandler(data) { - log(`peerMessageHandler ${data}`); + // log(`peerMessageHandler ${JSON.stringify(data)}`) let peerMessageType = data.message.type; let handler = this.peerMessageHandlers.get(peerMessageType); if (!handler) { @@ -198,9 +291,11 @@ class wsConnection { console.log(error.message); return; } - this.websocket.onopen = (event) => { + this.websocket.onopen = async (event) => { log("ws:connected"); - this.send({ type: "hello", user_id: this.userID, peer_id: this.peerID }); + let knownUsers = [...(await indexedDB.databases())].map((db) => db.name?.replace('user_', '')); + console.log('Network: Sending known users', knownUsers); + this.send({ type: "hello", user_id: this.userID, peer_id: this.peerID, known_users: knownUsers }); this.websocketPingInterval = window.setInterval(() => { if (!navigator.onLine) { return; @@ -215,7 +310,7 @@ class wsConnection { window.setTimeout(() => { this.connect(); }, this.retry * 1000); }; this.websocket.onmessage = (event) => { - log('ws:<-' + event.data.slice(0, 240)); + // log('ws:<-' + event.data.slice(0, 240)); let data = JSON.parse(event.data); let { type } = data; let handler = this.messageHandlers.get(type); @@ -263,7 +358,17 @@ class App { this.userID = ''; this.peerID = ''; this.posts = []; + this.isHeadless = false; + this.showLog = false; this.time = 0; + this.animals = ['shrew', 'jerboa', 'lemur', 'weasel', 'possum', 'possum', 'marmoset', 'planigale', 'mole', 'narwhal']; + this.adjectives = ['snazzy', 'whimsical', 'jazzy', 'bonkers', 'wobbly', 'spiffy', 'chirpy', 'zesty', 'bubbly', 'perky', 'sassy']; + this.router = { + route: App.Route.HOME, + userID: '', + postID: '', + mediaID: '' + }; } initMarkdown() { const renderer = new marked.Renderer(); @@ -379,16 +484,16 @@ class App { console.error("Service Worker registration failed:", error); }); } - addPost(userID, postText, imageData) { + addPost(userID, postText, mediaData, mediaType) { if ((typeof postText !== "string") || postText.length === 0) { log("Not posting an empty string..."); return; } - let post = new Post(this.username, userID, postText, new Date(), imageData); + let post = new Post(this.username, userID, postText, new Date(), mediaData); this.posts.push(post); // localStorage.setItem(key, JSON.stringify(posts)); addData(userID, post); - this.render(this.posts); + this.render(); } getPeerID() { let id = localStorage.getItem("peer_id"); @@ -406,10 +511,25 @@ class App { } return id; } + hashUserIdToIndices() { + let indices = []; + for (let char of this.userID) { + if (char !== '0' && char !== '-') { + indices.push(parseInt(char, 16)); + if (indices.length == 2) { + break; + } + } + } + return [indices[0], indices[1]]; + } getUsername() { let username = localStorage.getItem("dandelion_username"); - if (!username) { - username = "not_set"; + if (!username || username === "not_set") { + let [one, two] = this.hashUserIdToIndices(); + let adjective = this.adjectives[one % this.adjectives.length]; + let animal = this.animals[two % this.animals.length]; + username = `${adjective}_${animal}`; localStorage.setItem("dandelion_username", username); } return username; @@ -437,8 +557,7 @@ class App { window.addEventListener('online', async () => { log("online"); connection.connect(); - this.posts = await this.loadPosts(this.userID) ?? []; - this.render(this.posts); + this.render(); }); log(`Online status: ${navigator.onLine ? "online" : "offline"}`); } @@ -486,7 +605,23 @@ class App { let clearPostsButton = document.getElementById("clear_posts"); let updateApp = document.getElementById("update_app"); let ddlnLogoButton = document.getElementById('ddln_logo_button'); - // let addP = document.getElementById('button_add_pic') as HTMLDivElement; + // let addPic = document.getElementById('button_add_pic') as HTMLDivElement; + let filePickerLabel = document.getElementById('file_input_label'); + let filePicker = document.getElementById('file_input'); + let toggleDark = document.getElementById('toggle_dark'); + toggleDark.addEventListener('click', () => { + document.documentElement.style.setProperty('--main-bg-color', 'white'); + document.documentElement.style.setProperty('--main-fg-color', 'black'); + }); + filePicker?.addEventListener('change', async (event) => { + for (let file of filePicker.files) { + let buffer = await file.arrayBuffer(); + let type = this.addPost(this.userID, 'image...', buffer); + } + }); + filePickerLabel?.addEventListener('click', () => { + console.log("Add pic..."); + }); let usernameField = document.getElementById('username'); usernameField?.addEventListener('input', (event) => { this.username = event.target.innerText; @@ -505,10 +640,9 @@ class App { clearData(userID); // posts = posts.reverse(); addDataArray(userID, imported_posts); - posts = await this.loadPosts(userID) ?? []; - this.render(posts); + this.render(); }); - clearPostsButton.addEventListener('click', () => { clearData(userID); posts = []; this.render(posts); }); + clearPostsButton.addEventListener('click', () => { clearData(userID); posts = []; this.render(); }); let postButton = document.getElementById("button_post"); let postText = document.getElementById("textarea_post"); if (!(postButton && postText)) { @@ -533,9 +667,13 @@ class App { } ddlnLogoButton.addEventListener('click', () => { infoElement.style.display == 'none' ? infoElement.style.display = 'block' : infoElement.style.display = 'none'; }); } - async loadPosts(userID) { + async loadPosts(userID, postID) { this.timerStart(); - let posts = await getData(userID, new Date(2022, 8), new Date()); + let posts = []; + // if (postID) { + // posts = await gePostForUser(userID, postID); + // } + posts = await getData(userID, new Date(2022, 8), new Date()); if (posts.length > 0) { log(`Loaded ${posts.length} posts in ${this.timerDelta().toFixed(2)}ms`); return posts; @@ -545,24 +683,38 @@ class App { // addDataArray(userID, posts); // return await getData(userID, new Date(2022, 8), new Date()); } - async main() { - let urlParams = (new URL(window.location.href)).searchParams; - let connection_userID = urlParams.get('connect'); - let registration = undefined; - // if (urlParams.get("sw") === "true") { - registration = await this.registerServiceWorker(); - // } - if (connection_userID) { - console.log('connect', connection_userID); - localStorage.setItem("dandelion_id", connection_userID); + async purgeEmptyUsers() { + let knownUsers = [...(await indexedDB.databases())].map((db) => db.name?.replace('user_', '')); + if (!knownUsers) { + return; } - this.username = this.getUsername(); - document.getElementById('username').innerText = this.username; + for (let userID of knownUsers) { + let ids = await getAllIds(userID); + if (ids.length === 0) { + console.log(`Purging user ${userID}`); + indexedDB.deleteDatabase(`user_${userID}`); + } + console.log(`https://ddln.app/user/${userID}`); + } + } + async main() { + this.isHeadless = /\bHeadlessChrome\//.test(navigator.userAgent); let userID = this.getUserID(); let peerID = this.getPeerID(); this.userID = userID; this.peerID = peerID; - this.initButtons(userID, this.posts, registration); + this.getRoute(); + if (this.router.route === App.Route.CONNECT) { + console.log('connect', this.router.userID); + localStorage.setItem("dandelion_id", this.router.userID); + } + let urlParams = (new URL(window.location.href)).searchParams; + let connection_userID = urlParams.get('connect'); + let registration = undefined; + if (urlParams.has('log')) { + document.getElementById('info').style.display = "block"; + this.showLog = true; + } let time = 0; let delta = 0; // let isPersisted = await navigator?.storage?.persisted(); @@ -577,16 +729,19 @@ class App { // let code = await main.text(); // console.log(code); // registration.active.postMessage({type:"updateMain", code:code}); - this.posts = await this.loadPosts(userID) ?? []; + // this.posts = await this.loadPosts(userID) ?? []; // debugger; - this.timerStart(); - this.render(this.posts); // , (postID:string)=>{this.deletePost(userID, postID)} - let renderTime = this.timerDelta(); - log(`render took: ${renderTime.toFixed(2)}ms`); + await this.render(); // , (postID:string)=>{this.deletePost(userID, postID)} if (performance?.memory) { log(`memory used: ${(performance.memory.usedJSHeapSize / 1024 / 1024).toFixed(2)}Mb`); } - let connectURL = `https://${document.location.hostname}?connect=${this.userID}`; + // if (urlParams.get("sw") === "true") { + registration = await this.registerServiceWorker(); + // } + this.username = this.getUsername(); + document.getElementById('username').innerText = this.username; + this.initButtons(userID, this.posts, registration); + let connectURL = `https://${document.location.hostname}/connect/${this.userID}`; document.getElementById('connectURL').innerHTML = `connect`; let qrcode = await new QRCode(document.getElementById('qrcode'), { text: connectURL, @@ -596,9 +751,10 @@ class App { colorLight: "#ffffff", correctLevel: QRCode.CorrectLevel.H }); - let qrcodeImage = document.querySelector('#qrcode > img'); - qrcodeImage.classList.add('qrcode_image'); - log(`user:${userID} peer:${peerID}`); + document.querySelector('#qrcode > img').classList.add('qrcode_image'); + document.querySelector('#qrcode > canvas').classList.add('qrcode_image'); + log(`username:${this.username} user:${userID} peer:${peerID}`); + await this.purgeEmptyUsers(); let websocket = new wsConnection(userID, peerID); window.addEventListener('beforeunload', () => { websocket.disconnect(); }); this.initOffline(websocket); @@ -615,7 +771,43 @@ class App { // file.appendTo(document.getElementById('torrent-content')); // }) } - render(posts) { + // keep a map of posts to dom nodes. + // on re-render + // posts that are not in our list that we need at add + // posts that are in our list that we need to remove + // postsSet = new Set(); + async render() { + if (this.isHeadless) { + console.log('Headless so skipping render...'); + return; + } + this.timerStart(); + let posts = []; + switch (this.router.route) { + case App.Route.HOME: + case App.Route.CONNECT: { + posts = await this.loadPosts(this.userID) ?? []; + break; + } + case App.Route.USER: { + posts = await this.loadPosts(this.router.userID) ?? []; + break; + } + case App.Route.POST: { + posts = await this.loadPosts(this.router.userID, this.router.postID) ?? []; + break; + } + default: { + console.log("Render: got a route I didn't understand. Rendering HOME:", this.router.route); + posts = await this.loadPosts(this.userID) ?? []; + break; + } + } + // let newPostsSet = new Set(posts.map(post=>post.post_id)); + // let newPosts = (newPostsSet as any).difference(this.postsSet); + // // let removedPosts = (this.postsSet as any).difference(newPosts); + // let keepPosts = (this.postsSet as any).intersection(newPostsSet); + // let renderPosts = keepPosts.union(newPosts); const fragment = document.createDocumentFragment(); let contentDiv = document.getElementById("content"); if (!contentDiv) { @@ -625,7 +817,8 @@ class App { // let count = 0; for (let i = posts.length - 1; i >= 0; i--) { let postData = posts[i]; - let post = this.renderPost(postData, posts); + // this.postsSet.add(postData); + let post = this.renderPost(postData); if (post) { fragment.appendChild(post); // count++; @@ -638,13 +831,17 @@ class App { throw new Error("Couldn't get content div!"); } contentDiv.appendChild(fragment); + let renderTime = this.timerDelta(); + log(`render took: ${renderTime.toFixed(2)}ms`); + if (performance?.memory) { + log(`memory used: ${(performance.memory.usedJSHeapSize / 1024 / 1024).toFixed(2)}Mb`); + } } async deletePost(userID, postID) { deleteData(userID, postID); - this.posts = await this.loadPosts(userID) ?? []; - this.render(this.posts); + this.render(); } - renderPost(post, posts) { + renderPost(post) { if (!(post.hasOwnProperty("text"))) { throw new Error("Post is malformed!"); } @@ -652,26 +849,40 @@ class App { let timestamp = `${post.post_timestamp.toLocaleTimeString()} ยท ${post.post_timestamp.toLocaleDateString()}`; let deleteButton = document.createElement('button'); deleteButton.innerText = 'delete'; + deleteButton.onclick = () => { this.deletePost(post.author_id, post.post_id); }; let editButton = document.createElement('button'); editButton.innerText = 'edit'; - deleteButton.onclick = () => { this.deletePost(this.userID, post.post_id); }; + let shareButton = document.createElement('button'); + shareButton.innerText = 'share'; + shareButton.onclick = async () => { + let shareUrl = `https://${document.location.hostname}/user/${post.author_id}/post/${post.post_id}`; + await navigator.clipboard.writeText(shareUrl); + }; + let ownPost = post.author_id === this.userID; let postTemplate = `

-
- @${post.author} - - ${post.post_timestamp.toLocaleDateString()} - -
-
${marked.parse(post.text)}
-
`; +
+ @${post.author} - + ${post.post_timestamp.toLocaleDateString()} + + ${ownPost ? `` : ''} + ${ownPost ? `` : ''} + +
+
${marked.parse(post.text)}
+
`; containerDiv.innerHTML = postTemplate; - containerDiv.querySelector('#deleteButton')?.appendChild(deleteButton); - containerDiv.querySelector('#editButton')?.appendChild(editButton); + if (ownPost) { + containerDiv.querySelector('#deleteButton')?.appendChild(deleteButton); + containerDiv.querySelector('#editButton')?.appendChild(editButton); + } + containerDiv.querySelector('#shareButton')?.appendChild(shareButton); if (!("image_data" in post && post.image_data)) { // containerDiv.appendChild(timestampDiv); return containerDiv; // return null; } let image = document.createElement("img"); + image.title = `${(post.image_data.byteLength / 1024 / 1024).toFixed(2)}MBytes`; // const blob = new Blob([post.image_data as ArrayBuffer], { type: 'image/png' }); const blob = new Blob([post.image_data]); const url = URL.createObjectURL(blob); @@ -681,11 +892,61 @@ class App { image.src = url; // image.src = image.src = "data:image/png;base64," + post.image; image.className = "postImage"; + image.onclick = () => { App.maximizeElement(image); }; containerDiv.appendChild(image); // containerDiv.appendChild(timestampDiv); return containerDiv; } + static maximizeElement(element) { + element.style.transform = "scale(2.0)"; + } + getRoute() { + app.router.userID = this.userID; + let path = document.location.pathname; + console.log(">>>>>>>>>>>>>>>>>>>>>>>>>", path); + const regex = "(user/([a-zA-Z0-9\-]+)/?(post/([a-zA-Z0-9\-]+)?/?)?(media/([0-9]+)?)?)|(connect/([a-zA-Z0-9\-]+))"; + const match = path.match(new RegExp(regex)); + if (match) { + if (match[8]) { // Check for the connect route + this.router.userID = match[8]; + this.router.route = App.Route.CONNECT; + } + else { + this.router.userID = match[2]; + this.router.postID = match[4]; + this.router.mediaID = match[6]; + if (this.router.mediaID) { + this.router.route = App.Route.MEDIA; + } + else if (this.router.postID) { + this.router.route = App.Route.POST; + } + else { + this.router.route = App.Route.USER; + } + } + } + console.log(">>>>>>>>>>>>>", this.router, App.Route[this.router.route]); + // user = /user/ + // post = /user//post/ + // media = /user//post//media/ + // group = /group/ID/post/ + // hashtag = /hashtag/ -- maybe only hastags in groups + // home = / + } } +(function (App) { + let Route; + (function (Route) { + Route[Route["USER"] = 0] = "USER"; + Route[Route["POST"] = 1] = "POST"; + Route[Route["MEDIA"] = 2] = "MEDIA"; + Route[Route["GROUP"] = 3] = "GROUP"; + Route[Route["HOME"] = 4] = "HOME"; + Route[Route["CONNECT"] = 5] = "CONNECT"; + })(Route = App.Route || (App.Route = {})); + ; +})(App || (App = {})); let app = new App(); window.addEventListener("load", app.main.bind(app)); //# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/static/main.js.map b/static/main.js.map new file mode 100644 index 0000000..afc59f1 --- /dev/null +++ b/static/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/static/peers.js b/static/peers.js new file mode 100644 index 0000000..add60e2 --- /dev/null +++ b/static/peers.js @@ -0,0 +1,20 @@ +var PeerMessageTypes; +(function (PeerMessageTypes) { + PeerMessageTypes[PeerMessageTypes["HELLO"] = 0] = "HELLO"; +})(PeerMessageTypes || (PeerMessageTypes = {})); +export class Peer { + constructor() { + this.peer_id = ''; + this.state = 'ready'; + } + connect(peer_id) { + } +} +export class PeerManager { + constructor() { + this.peers = []; + } + connectPeer(peer_id) { + } +} +//# sourceMappingURL=peers.js.map \ No newline at end of file diff --git a/static/peers.js.map b/static/peers.js.map new file mode 100644 index 0000000..24e68e0 --- /dev/null +++ b/static/peers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"peers.js","sourceRoot":"","sources":["../src/peers.ts"],"names":[],"mappings":"AACA,IAAK,gBAGJ;AAHD,WAAK,gBAAgB;IACjB,yDAAK,CAAA;AAET,CAAC,EAHI,gBAAgB,KAAhB,gBAAgB,QAGpB;AAED,MAAM,OAAO,IAAI;IAAjB;QACI,YAAO,GAAU,EAAE,CAAC;QAEpB,UAAK,GAAmD,OAAO,CAAC;IAIpE,CAAC;IAHG,OAAO,CAAC,OAAc;IAEtB,CAAC;CACJ;AAED,MAAM,OAAO,WAAW;IAAxB;QACI,UAAK,GAAU,EAAE,CAAC;IAOtB,CAAC;IALG,WAAW,CAAC,OAAc;IAE1B,CAAC;CAGJ"} \ No newline at end of file diff --git a/robots.txt b/static/robots.txt similarity index 100% rename from robots.txt rename to static/robots.txt diff --git a/static/sw.js b/static/sw.js new file mode 100644 index 0000000..335f1d3 --- /dev/null +++ b/static/sw.js @@ -0,0 +1,117 @@ +"use strict"; +const debugLog = false; +// Establish a cache name +const cacheName = "dandelion_cache_v1"; +const contentToCache = [ + '/static/index.html', + '/static/main.css', + '/static/main.js', + '/static/lib/marked.min.js', + '/static/lib/qrcode.min.js', + '/static/db.js', + '/static/favicon.ico' +]; +self.addEventListener("install", (e) => { + e.waitUntil((async () => { + const cache = await caches.open(cacheName); + console.log("[Service Worker] Caching all: app shell and content", contentToCache); + try { + await cache.addAll(contentToCache); + } + catch (e) { + debugLog ? console.log(e) : null; + } + })()); +}); +async function staleWhileRevalidate(event) { + let cache = await caches.open(cacheName); + let response = await cache.match(event.request); + if (response) { + debugLog ? console.log('Service Worker: Cache hit', event.request.url) : null; + } + const fetchPromise = (async () => { + debugLog ? console.log('Service Worker: Fetching', event.request.url) : null; + let networkResponse = null; + try { + networkResponse = await fetch(event.request); + } + catch (e) { + debugLog ? console.log('Service Worker: Failed to fetch', e) : null; + return new Response('Network error occurred', { + status: 404, + statusText: 'Cache miss and fetch failed', + headers: { 'Content-Type': 'text/plain' } + }); + } + debugLog ? console.log('Service Worker: Updating cache', event.request.url) : null; + try { + await cache.put(event.request, networkResponse.clone()); + } + catch (e) { + debugLog ? console.log('Service Worker: failed to update cache', event.request.url, e) : null; + } + debugLog ? console.log('Service Worker: Returning networkResponse', event.request.url) : null; + return networkResponse; + })(); + debugLog ? console.log('Service Worker: Returning return response || fetchPromise', event.request.url) : null; + return response || fetchPromise; + // if (networkResponse) { + // cache.put(event.request, networkResponse.clone()) + // return networkResponse; + // } + // caches.open(cacheName) + // .then(function (cache) { + // return cache.match(event.request) + // .then(function (response) { + // var fetchPromise = fetch(event.request) + // .then(function (networkResponse) { + // cache.put(event.request, networkResponse.clone()); + // return networkResponse; + // }); + // return response || fetchPromise; + // }); + // }) +} +// async function responder(event: any) { +// debugLog ? console.log('Fetching', event.request.url) : null; +// let response = await fetch(event.request); +// if (!response) { +// debugLog ? console.log('Fetch failed, falling back to cache', event.request.url) : null; +// let cacheMatch = await caches.match(event.request); +// if (!cacheMatch) { +// // DUnno what to return here! +// } +// return cacheMatch; +// } +// if (response.status === 206) { +// debugLog ? console.log('Not caching partial content') : null; +// return response; +// } +// debugLog ? console.log('Fetch successful, updating cache', event.request.url) : null; +// const cache = await caches.open(cacheName); +// try { +// cache.put(event.request, response.clone()).catch((error) => debugLog ? console.log('failed to cache', event.request, error)) : null; +// } catch (e) { +// console.log('failed to cache', event.request) +// } +// return response; +// } +self.addEventListener('fetch', function (event) { + event.respondWith(staleWhileRevalidate(event)); + // event.respondWith(responder(event)); +}); +addEventListener("message", async (e) => { + debugLog ? console.log(`Message received:`, e.data) : null; + switch (e.data.type) { + case "update_app": + const cache = await caches.open(cacheName); + debugLog ? console.log(`[Service Worker] Caching resources`) : null; + // cache.put("/main.js", new Response()); + for (let item of contentToCache) { + cache.delete(item); + } + await cache.addAll(contentToCache); + break; + } +}); +//# sourceMappingURL=sw.js.map \ No newline at end of file diff --git a/static/sw.js.map b/static/sw.js.map new file mode 100644 index 0000000..4190338 --- /dev/null +++ b/static/sw.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sw.js","sourceRoot":"","sources":["../src/sw.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/static/test_data/thrust.webm b/static/test_data/thrust.webm new file mode 100644 index 0000000..9b32a94 Binary files /dev/null and b/static/test_data/thrust.webm differ diff --git a/static/test_data/wingit.mp4 b/static/test_data/wingit.mp4 new file mode 100644 index 0000000..2e10c2e Binary files /dev/null and b/static/test_data/wingit.mp4 differ diff --git a/static/test_data/yt-dlp b/static/test_data/yt-dlp new file mode 100755 index 0000000..ef67b03 Binary files /dev/null and b/static/test_data/yt-dlp differ diff --git a/virgil.woff2 b/static/virgil.woff2 similarity index 100% rename from virgil.woff2 rename to static/virgil.woff2 diff --git a/static/webRTC.js b/static/webRTC.js new file mode 100644 index 0000000..02af802 --- /dev/null +++ b/static/webRTC.js @@ -0,0 +1,96 @@ +"use strict"; +class PeerManager { + connect(peerID) { + // Connect to the peer that has the peer id peerID + } + disconnect(peerID) { + } +} +class PeerConnection { +} +PeerConnection.config = { + iceServers: [ + { urls: "stun:stun.l.google.com" }, + { urls: "stun:stun1.l.google.com" }, + { urls: "stun:stun2.l.google.com" }, + { urls: "stun:stun3.l.google.com" }, + { urls: "stun:stun4.l.google.com" }, + ], +}; +const config = { + iceServers: [{ urls: "stun:stun.mystunserver.tld" }], +}; +let polite = true; +// const signaler = new SignalingChannel(); +const signaler = {}; +const pc = new RTCPeerConnection(config); +const constraints = { audio: true, video: true }; +const selfVideo = document.querySelector("video.selfview"); +const remoteVideo = document.querySelector("video.remoteview"); +async function start() { + try { + const stream = await navigator.mediaDevices.getUserMedia(constraints); + for (const track of stream.getTracks()) { + pc.addTrack(track, stream); + } + // selfVideo.srcObject = stream; + } + catch (err) { + console.error(err); + } +} +pc.ontrack = ({ track, streams }) => { + track.onunmute = () => { + // if (remoteVideo.srcObject) { + // return; + // } + // remoteVideo.srcObject = streams[0]; + }; +}; +let makingOffer = false; +pc.onnegotiationneeded = async () => { + try { + makingOffer = true; + await pc.setLocalDescription(); + signaler.send({ description: pc.localDescription }); + } + catch (err) { + console.error(err); + } + finally { + makingOffer = false; + } +}; +pc.onicecandidate = ({ candidate }) => signaler.send({ candidate }); +let ignoreOffer = false; +signaler.onmessage = async ({ data: { description, candidate } }) => { + try { + if (description) { + const offerCollision = description.type === "offer" && + (makingOffer || pc.signalingState !== "stable"); + ignoreOffer = !polite && offerCollision; + if (ignoreOffer) { + return; + } + await pc.setRemoteDescription(description); + if (description.type === "offer") { + await pc.setLocalDescription(); + signaler.send({ description: pc.localDescription }); + } + } + else if (candidate) { + try { + await pc.addIceCandidate(candidate); + } + catch (err) { + if (!ignoreOffer) { + throw err; + } + } + } + } + catch (err) { + console.error(err); + } +}; +//# sourceMappingURL=webRTC.js.map \ No newline at end of file diff --git a/static/webRTC.js.map b/static/webRTC.js.map new file mode 100644 index 0000000..b1ecd7d --- /dev/null +++ b/static/webRTC.js.map @@ -0,0 +1 @@ +{"version":3,"file":"webRTC.js","sourceRoot":"","sources":["../src/webRTC.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/sw.js b/sw.js deleted file mode 100644 index c98eccc..0000000 --- a/sw.js +++ /dev/null @@ -1,62 +0,0 @@ -"use strict"; -// Establish a cache name -const cacheName = "dandelion_cache_v1"; -const contentToCache = [ - '/index.html', - '/main.css', - '/main.js', - 'lib//marked.min.js', - 'lib/qrcode.min.js', - '/db.js', - '/favicon.ico' -]; -self.addEventListener("install", (e) => { - e.waitUntil((async () => { - const cache = await caches.open(cacheName); - console.log("[Service Worker] Caching all: app shell and content", contentToCache); - await cache.addAll(contentToCache); - })()); -}); -async function responder(event) { - console.log('Fetching', event.request.url); - let response = await fetch(event.request); - if (!response) { - console.log('Fetch failed, falling back to cache', event.request.url); - let cacheMatch = await caches.match(event.request); - if (!cacheMatch) { - // DUnno what to return here! - } - return cacheMatch; - } - if (response.status === 206) { - console.log('Not caching partial content'); - return response; - } - console.log('Fetch successful, updating cache'); - const cache = await caches.open(cacheName); - try { - cache.put(event.request, response.clone()).catch((error) => console.log('failed to cache', event.request, error)); - } - catch (e) { - console.log('failed to cache', event.request); - } - return response; -} -self.addEventListener('fetch', function (event) { - event.respondWith(responder(event)); -}); -addEventListener("message", async (e) => { - console.log(`Message received:`, e.data); - switch (e.data.type) { - case "update_app": - const cache = await caches.open(cacheName); - console.log(`[Service Worker] Caching resources`); - // cache.put("/main.js", new Response()); - for (let item of contentToCache) { - cache.delete(item); - } - await cache.addAll(contentToCache); - break; - } -}); -//# sourceMappingURL=sw.js.map \ No newline at end of file diff --git a/sw.js.map b/sw.js.map deleted file mode 100644 index 4752727..0000000 --- a/sw.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"sw.js","sourceRoot":"","sources":["src/sw.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7ab1826..d922b63 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./", /* Redirect output structure to the directory. */ + "outDir": "./static", /* Redirect output structure to the directory. */ "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */