WIP PWA for Grain
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add auth service wrapping quickslice-client-js

+67
+67
src/services/auth.js
··· 1 + import { createQuicksliceClient } from 'quickslice-client-js'; 2 + 3 + class AuthService { 4 + #client = null; 5 + #user = null; 6 + #listeners = new Set(); 7 + #initialized = false; 8 + 9 + async init() { 10 + if (this.#initialized) return; 11 + 12 + this.#client = await createQuicksliceClient({ 13 + server: 'https://quickslice-production-9cf4.up.railway.app', 14 + clientId: 'client_h62Ea0FUeXTJ4pWBg4ZIkQ', 15 + scope: 'atproto transition:generic' 16 + }); 17 + 18 + // Handle OAuth callback if present 19 + if (window.location.search.includes('code=')) { 20 + await this.#client.handleRedirectCallback(); 21 + window.history.replaceState({}, '', window.location.pathname); 22 + } 23 + 24 + // Load user if authenticated 25 + if (await this.#client.isAuthenticated()) { 26 + await this.#loadUser(); 27 + } 28 + 29 + this.#initialized = true; 30 + } 31 + 32 + async #loadUser() { 33 + const { did } = this.#client.getUser(); 34 + const result = await this.#client.query(` 35 + query { viewer { handle displayName avatar { url } } } 36 + `); 37 + this.#user = { did, ...result.data.viewer }; 38 + this.#notify(); 39 + } 40 + 41 + async login(handle) { 42 + await this.#client.loginWithRedirect({ handle }); 43 + } 44 + 45 + logout() { 46 + this.#client.logout(); 47 + } 48 + 49 + get user() { 50 + return this.#user; 51 + } 52 + 53 + get isAuthenticated() { 54 + return !!this.#user; 55 + } 56 + 57 + subscribe(callback) { 58 + this.#listeners.add(callback); 59 + return () => this.#listeners.delete(callback); 60 + } 61 + 62 + #notify() { 63 + this.#listeners.forEach(cb => cb(this.#user)); 64 + } 65 + } 66 + 67 + export const auth = new AuthService();