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

Combine all css files

kishka.cc a84b2ffd 763f37bd

verified
Changed files
+386 -155
app
+386
app/src/privacypin.css
··· 1 + .container-sl { 2 + display: flex; 3 + justify-content: space-between; /* This will align the elements on opposite sides of the container */ 4 + } 5 + 6 + .element-al, 7 + .element-ar { 8 + flex: 1; /* Make the elements take up equal width */ 9 + } 10 + 11 + .element-al { 12 + text-align: left; 13 + } 14 + 15 + .element-ar { 16 + text-align: right; 17 + } 18 + 19 + body { 20 + font-family: sans-serif; 21 + background: #f9fafb; 22 + margin: 0; 23 + display: flex; 24 + justify-content: center; 25 + } 26 + 27 + .app { 28 + width: 100%; 29 + background: #f9fafb; 30 + } 31 + 32 + .svg-icon { 33 + width: 25px; 34 + height: 25px; 35 + margin: auto; 36 + } 37 + 38 + header { 39 + background: #fff; 40 + border-bottom: 1px solid #e5e7eb; 41 + padding: 0.75rem 1rem; 42 + display: flex; 43 + justify-content: space-between; 44 + } 45 + 46 + header h1 { 47 + font-size: 1rem; 48 + margin: 0; 49 + display: flex; 50 + align-items: center; 51 + } 52 + 53 + header .icon-btn { 54 + border: none; 55 + background: none; 56 + cursor: pointer; 57 + padding: 0.4rem; 58 + } 59 + 60 + .status { 61 + background: #fff; 62 + border-bottom: 1px solid #f3f4f6; 63 + padding: 0.75rem 1rem; 64 + display: flex; 65 + justify-content: space-between; 66 + align-items: center; 67 + font-size: 0.9rem; 68 + } 69 + 70 + .content { 71 + flex: 1; 72 + overflow-y: auto; 73 + padding: 1rem; 74 + } 75 + 76 + .friends-header { 77 + display: flex; 78 + align-items: center; 79 + gap: 0.5rem; 80 + margin-bottom: 1rem; 81 + } 82 + 83 + .friend-card { 84 + background: #fff; 85 + border: 1px solid #e5e7eb; 86 + border-radius: 8px; 87 + padding: 1rem; 88 + margin-bottom: 0.75rem; 89 + display: flex; 90 + justify-content: space-between; 91 + align-items: center; 92 + } 93 + 94 + .friend-actions { 95 + display: flex; 96 + align-items: center; 97 + gap: 0.1rem; 98 + } 99 + 100 + .friend-actions .view-btn { 101 + cursor: pointer; 102 + border-radius: 6px; 103 + border: 1px solid #d1d5db; 104 + background: #fff; 105 + padding: 0.3rem 0.5rem; 106 + font-size: 0.8rem; 107 + } 108 + 109 + .friend-actions .view-btn:hover { 110 + background: #f3f4f6; 111 + } 112 + 113 + .menu-icon { 114 + width: 16px; 115 + height: 16px; 116 + margin: 0; 117 + } 118 + 119 + .friend-actions { 120 + cursor: pointer; 121 + font-size: 1.2rem; 122 + color: #6b7280; 123 + padding: 0 0.3rem; 124 + user-select: none; 125 + } 126 + 127 + .friend-actions { 128 + color: #111827; 129 + } 130 + 131 + .empty-state { 132 + text-align: center; 133 + padding: 3rem 1rem; 134 + color: #6b7280; 135 + } 136 + 137 + .empty-state button { 138 + margin-top: 0.75rem; 139 + padding: 0.5rem 1rem; 140 + border: none; 141 + border-radius: 6px; 142 + background: #3b82f6; 143 + color: white; 144 + cursor: pointer; 145 + } 146 + 147 + .friend-actions button img { 148 + width: 16px; 149 + height: 16px; 150 + vertical-align: middle; 151 + margin-right: 4px; 152 + } 153 + 154 + body { 155 + font-family: system-ui, sans-serif; 156 + background: #f9fafb; 157 + display: flex; 158 + align-items: center; 159 + justify-content: center; 160 + height: 100vh; 161 + margin: 0; 162 + } 163 + 164 + .card { 165 + max-width: 90%; 166 + background: white; 167 + border: 1px solid #d1d5db; 168 + border-radius: 8px; 169 + padding: 1.5rem; 170 + box-sizing: border-box; 171 + } 172 + 173 + .header { 174 + text-align: center; 175 + margin-bottom: 1.5rem; 176 + } 177 + 178 + .icon-circle { 179 + width: 64px; 180 + height: 64px; 181 + background: #dbeafe; 182 + border-radius: 50%; 183 + display: flex; 184 + align-items: center; 185 + justify-content: center; 186 + margin: 0 auto 1rem; 187 + } 188 + 189 + .icon-circle img { 190 + width: 32px; 191 + height: 32px; 192 + } 193 + 194 + h1 { 195 + font-size: 1.5rem; 196 + } 197 + 198 + p { 199 + font-size: 0.9rem; 200 + color: #6b7280; 201 + } 202 + 203 + .actions { 204 + display: flex; 205 + flex-direction: column; 206 + gap: 1rem; 207 + } 208 + 209 + label { 210 + display: block; 211 + font-size: 0.85rem; 212 + font-weight: 600; 213 + margin-bottom: 0.25rem; 214 + } 215 + 216 + input { 217 + width: 100%; 218 + padding: 0.5rem 0.75rem; 219 + border: 1px solid #d1d5db; 220 + border-radius: 4px; 221 + font-size: 0.95rem; 222 + box-sizing: border-box; 223 + } 224 + 225 + input:focus { 226 + outline: none; 227 + border-color: #2563eb; 228 + } 229 + 230 + button { 231 + width: 100%; 232 + padding: 0.6rem; 233 + font-size: 0.95rem; 234 + border-radius: 4px; 235 + cursor: pointer; 236 + /*transition: background 0.2s ease;*/ 237 + display: flex; 238 + align-items: center; 239 + justify-content: center; 240 + } 241 + 242 + .btn-primary { 243 + background: #2563eb; 244 + color: white; 245 + border: none; 246 + } 247 + 248 + .btn-primary:hover { 249 + background: #1d4ed8; 250 + } 251 + 252 + .btn-secondary { 253 + background: white; 254 + gap: 0.5rem; 255 + border: 1px solid #d1d5db; 256 + } 257 + 258 + .btn-secondary:hover { 259 + background: #f3f4f6; 260 + } 261 + 262 + .btn-secondary img { 263 + width: 16px; 264 + height: 16px; 265 + } 266 + 267 + .hint { 268 + font-size: 0.75rem; 269 + } 270 + 271 + body { 272 + font-family: system-ui, sans-serif; 273 + background: #f9fafb; 274 + display: flex; 275 + align-items: center; 276 + justify-content: center; 277 + height: 100vh; 278 + margin: 0; 279 + } 280 + 281 + .card { 282 + max-width: 90%; 283 + background: white; 284 + border: 1px solid #d1d5db; 285 + border-radius: 8px; 286 + padding: 1.5rem; 287 + box-sizing: border-box; 288 + } 289 + 290 + .header { 291 + text-align: center; 292 + margin-bottom: 1.5rem; 293 + } 294 + 295 + .icon-circle { 296 + width: 64px; 297 + height: 64px; 298 + background: #dbeafe; 299 + border-radius: 50%; 300 + display: flex; 301 + align-items: center; 302 + justify-content: center; 303 + margin: 0 auto 1rem; 304 + } 305 + 306 + .icon-circle img { 307 + width: 48px; 308 + height: 48px; 309 + } 310 + 311 + h1 { 312 + font-size: 1.5rem; 313 + } 314 + 315 + p { 316 + font-size: 0.9rem; 317 + color: #6b7280; 318 + } 319 + 320 + .actions { 321 + display: flex; 322 + flex-direction: column; 323 + gap: 1rem; 324 + } 325 + 326 + label { 327 + display: block; 328 + font-size: 0.85rem; 329 + font-weight: 600; 330 + margin-bottom: 0.25rem; 331 + } 332 + 333 + input { 334 + width: 100%; 335 + padding: 0.5rem 0.75rem; 336 + border: 1px solid #d1d5db; 337 + border-radius: 4px; 338 + font-size: 0.95rem; 339 + box-sizing: border-box; 340 + } 341 + 342 + input:focus { 343 + outline: none; 344 + border-color: #2563eb; 345 + } 346 + 347 + button { 348 + width: 100%; 349 + padding: 0.6rem; 350 + font-size: 0.95rem; 351 + border-radius: 4px; 352 + cursor: pointer; 353 + /*transition: background 0.2s ease;*/ 354 + display: flex; 355 + align-items: center; 356 + justify-content: center; 357 + } 358 + 359 + .btn-primary { 360 + background: #2563eb; 361 + color: white; 362 + border: none; 363 + } 364 + 365 + .btn-primary:hover { 366 + background: #1d4ed8; 367 + } 368 + 369 + .btn-qr { 370 + background: white; 371 + gap: 0.5rem; 372 + border: 1px solid #d1d5db; 373 + } 374 + 375 + .btn-qr:hover { 376 + background: #f3f4f6; 377 + } 378 + 379 + .btn-qr img { 380 + width: 20px; 381 + height: 16px; 382 + } 383 + 384 + .hint { 385 + font-size: 0.75rem; 386 + }
-116
app/src/settings-page copy/settings.css
··· 1 - body { 2 - font-family: system-ui, sans-serif; 3 - background: #f9fafb; 4 - display: flex; 5 - align-items: center; 6 - justify-content: center; 7 - height: 100vh; 8 - margin: 0; 9 - } 10 - 11 - .card { 12 - max-width: 90%; 13 - background: white; 14 - border: 1px solid #d1d5db; 15 - border-radius: 8px; 16 - padding: 1.5rem; 17 - box-sizing: border-box; 18 - } 19 - 20 - .header { 21 - text-align: center; 22 - margin-bottom: 1.5rem; 23 - } 24 - 25 - .icon-circle { 26 - width: 64px; 27 - height: 64px; 28 - background: #dbeafe; 29 - border-radius: 50%; 30 - display: flex; 31 - align-items: center; 32 - justify-content: center; 33 - margin: 0 auto 1rem; 34 - } 35 - 36 - .icon-circle img { 37 - width: 32px; 38 - height: 32px; 39 - } 40 - 41 - h1 { 42 - font-size: 1.5rem; 43 - } 44 - 45 - p { 46 - font-size: 0.9rem; 47 - color: #6b7280; 48 - } 49 - 50 - .actions { 51 - display: flex; 52 - flex-direction: column; 53 - gap: 1rem; 54 - } 55 - 56 - label { 57 - display: block; 58 - font-size: 0.85rem; 59 - font-weight: 600; 60 - margin-bottom: 0.25rem; 61 - } 62 - 63 - input { 64 - width: 100%; 65 - padding: 0.5rem 0.75rem; 66 - border: 1px solid #d1d5db; 67 - border-radius: 4px; 68 - font-size: 0.95rem; 69 - box-sizing: border-box; 70 - } 71 - 72 - input:focus { 73 - outline: none; 74 - border-color: #2563eb; 75 - } 76 - 77 - button { 78 - width: 100%; 79 - padding: 0.6rem; 80 - font-size: 0.95rem; 81 - border-radius: 4px; 82 - cursor: pointer; 83 - /*transition: background 0.2s ease;*/ 84 - display: flex; 85 - align-items: center; 86 - justify-content: center; 87 - } 88 - 89 - .btn-primary { 90 - background: #2563eb; 91 - color: white; 92 - border: none; 93 - } 94 - 95 - .btn-primary:hover { 96 - background: #1d4ed8; 97 - } 98 - 99 - .btn-secondary { 100 - background: white; 101 - gap: 0.5rem; 102 - border: 1px solid #d1d5db; 103 - } 104 - 105 - .btn-secondary:hover { 106 - background: #f3f4f6; 107 - } 108 - 109 - .btn-secondary img { 110 - width: 16px; 111 - height: 16px; 112 - } 113 - 114 - .hint { 115 - font-size: 0.75rem; 116 - }
-24
app/src/settings-page copy/settings.html
··· 1 - <!doctype html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8" /> 5 - <script type="module" src="./settings.ts"></script> 6 - <link rel="stylesheet" href="./settings.css" /> 7 - </head> 8 - 9 - <body> 10 - <div class="card"> 11 - <div class="actions" x-data="settingsPageState"> 12 - <h3>Settings</h3> 13 - 14 - <button class="btn-primary" @click="goto('home')"> 15 - Back to Home 16 - </button> 17 - 18 - <button class="btn-secondary" @click="await debugLogout()"> 19 - Signout 20 - </button> 21 - </div> 22 - </div> 23 - </body> 24 - </html>
-15
app/src/settings-page copy/settings.ts
··· 1 - import Alpine from "alpinejs"; 2 - import { Store } from "../utils/store.ts"; 3 - import { goto } from "../utils/tools.ts"; 4 - 5 - Alpine.data("settingsPageState", () => ({ 6 - async debugLogout() { 7 - await Store.reset(); 8 - goto("signup"); 9 - }, 10 - goto(newLocation: string) { 11 - goto(newLocation); 12 - }, 13 - })); 14 - 15 - Alpine.start();