Self-hosted, federated location sharing app and server that prioritizes user privacy and security
end-to-end-encryption location-sharing privacy self-hosted federated

New admin section, allowing for the generation of signup keys on the homepage

Clicking scan qr button on signup page now autofills the address to "http://127.0.0.1:3000" instead of "dummy server address".

The settings button now opens the settings page(for next commit)

thank you azom.dev for making the api.ts easier to use

kishka.cc 82d315fc 1e5f58e7

verified
Changed files
+53 -6
app
src
home-page
signup-page
+39 -4
app/src/home-page/home.html
··· 29 29 <div class="content"> 30 30 <div class="friends-header"> 31 31 <h2 style="font-size: 1rem; margin: 0">Friends</h2> 32 - <span style="color: #6b7280; font-size: 0.9rem">(<span x-text="friends.length"></span>)</span> 32 + <span style="color: #6b7280; font-size: 0.9rem" 33 + >(<span x-text="friends.length"></span>)</span 34 + > 33 35 </div> 34 36 35 37 <template x-if="friends.length > 0"> ··· 38 40 <div class="friend-card"> 39 41 <strong x-text="friend.name"></strong> 40 42 <div class="friend-actions"> 41 - <button class="view-btn" @click="viewLocation(friend.id)"><img src="/src/assets/pin.svg" alt="Pin Icon" />View</button> 42 - <span class="menu-icon" @click="friendOptions(friend.id)"></span> 43 - <img class="menu-icon" src="/src/assets/three-dots.svg" alt="Pin Icon" /> 43 + <button 44 + class="view-btn" 45 + @click="viewLocation(friend.id)" 46 + > 47 + <img 48 + src="/src/assets/pin.svg" 49 + alt="Pin Icon" 50 + />View 51 + </button> 52 + <span 53 + class="menu-icon" 54 + @click="friendOptions(friend.id)" 55 + ></span> 56 + <img 57 + class="menu-icon" 58 + src="/src/assets/three-dots.svg" 59 + alt="Pin Icon" 60 + /> 44 61 </div> 45 62 </div> 46 63 </template> ··· 55 72 <button @click="addFriend()">Add Friend</button> 56 73 </div> 57 74 </template> 75 + </div> 76 + 77 + <!-- Admin --> 78 + <div x-if="isAdmin()"> 79 + <div class="content" style="text-align: center"> 80 + <h4>Admin Controls:</h4> 81 + <div style="display: flex; justify-content: center"> 82 + <button @click="generateSignupKey()"> 83 + Generate signup key 84 + </button> 85 + </div> 86 + <div 87 + style="display: flex; justify-content: center" 88 + x-show="newSignupKey != ''" 89 + > 90 + <p>New signup key: <a x-text="newSignupKey"></a></p> 91 + </div> 92 + </div> 58 93 </div> 59 94 </div> 60 95 </body>
+13 -1
app/src/home-page/home.ts
··· 1 1 import Alpine from "alpinejs"; 2 + import { goto } from "../utils/tools.ts"; 3 + import { Store } from "../utils/store.ts"; 4 + import { generateSignupKey } from "../utils/api.ts"; 2 5 3 6 Alpine.data("homePageState", () => ({ 4 7 friends: [ ··· 6 9 { id: "456", name: "Bob Smith" }, 7 10 { id: "789", name: "Carol Davis" }, 8 11 ], 12 + newSignupKey: "", 9 13 10 14 timeAgo() { 11 15 return "2m ago"; ··· 24 28 }, 25 29 26 30 openSettings() { 27 - alert("Settings would open here"); 31 + goto("settings"); 32 + }, 33 + 34 + async generateSignupKey() { 35 + this.newSignupKey = await generateSignupKey(); 36 + }, 37 + 38 + isAdmin() { 39 + return Store.get("is_admin"); 28 40 }, 29 41 })); 30 42
+1 -1
app/src/signup-page/signup.ts
··· 22 22 async scanQR() { 23 23 this.isDoingStuff = true; 24 24 await new Promise((resolve) => setTimeout(resolve, 1000)); 25 - this.serverAddress = "dummy server address"; 25 + this.serverAddress = "http://127.0.0.1:3000"; 26 26 this.signupKey = "dummy signup key"; 27 27 this.isDoingStuff = false; 28 28 },