Thread viewer for Bluesky

moved global API clients to api.js

+47 -33
+12
src/api.ts
··· 1 1 import { AuthenticatedAPI } from "./api/authenticated_api"; 2 2 import { BlueskyAPI, HiddenRepliesError, URLError } from "./api/bluesky_api"; 3 3 import { APIError, Minisky } from "./api/minisky"; 4 + import { settings } from "./models/settings.svelte"; 4 5 5 6 export { AuthenticatedAPI, BlueskyAPI, Minisky }; 6 7 export { APIError, HiddenRepliesError, URLError }; 8 + 9 + export let appView = new BlueskyAPI('api.bsky.app'); 10 + export let blueAPI = new BlueskyAPI('blue.mackuba.eu'); 11 + export let accountAPI = new AuthenticatedAPI(); 12 + export let api: BlueskyAPI; 13 + 14 + export function setAPI() { 15 + api = (accountAPI.isLoggedIn && !settings.incognitoMode) ? accountAPI : appView; 16 + } 17 + 18 + setAPI();
+2 -2
src/api/authenticated_api.ts
··· 27 27 export class AuthenticatedAPI extends BlueskyAPI { 28 28 user: json; 29 29 30 - constructor(host?: string | null | undefined) { 30 + constructor() { 31 31 let config = new LocalStorageConfig(); 32 - let pds: string | null = host || config.user.pdsEndpoint || null; 32 + let pds: string | null = config.user.pdsEndpoint || null; 33 33 super(pds, config); 34 34 this.user = config.user; 35 35 }
+1
src/api/bluesky_api.ts
··· 1 1 import { HandleCache } from './handle_cache.js'; 2 + import { blueAPI, appView } from '../api.js'; 2 3 import { APIError, Minisky, type FetchAllOnPageLoad, type MiniskyConfig, type MiniskyOptions } from './minisky.js'; 3 4 import { atURI, feedPostTime } from '../utils.js'; 4 5 import { Post } from '../models/posts.js';
+1
src/api/identity.ts
··· 1 + import { appView } from '../api.js'; 1 2 import { APIError } from './minisky.js'; 2 3 3 4 /**
+3 -1
src/components/UserAutocomplete.svelte
··· 1 1 <script lang="ts"> 2 + import { api } from '../api.js'; 3 + 2 4 export type AutocompleteUser = { 3 5 did: string; 4 6 handle: string; ··· 61 63 } 62 64 63 65 async function fetchAutocomplete(query: string) { 64 - let users = await accountAPI.autocompleteUsers(query) as AutocompleteUser[]; 66 + let users = await api.autocompleteUsers(query) as AutocompleteUser[]; 65 67 66 68 let selectedDIDs = new Set(selectedUserDIDs); 67 69 users = users.filter(u => !selectedDIDs.has(u.did));
+1
src/components/embeds/QuoteComponent.svelte
··· 1 1 <script lang="ts"> 2 + import { api } from '../../api.js'; 2 3 import { getPostContext } from '../posts/PostComponent.svelte'; 3 4 import { BasePost, Post, MissingPost } from '../../models/posts.js'; 4 5 import { InlineRecordEmbed, InlineRecordWithMediaEmbed } from '../../models/embeds.js';
+1
src/components/posts/BlockedPostView.svelte
··· 1 1 <script lang="ts"> 2 + import { api } from '../../api.js'; 2 3 import { BlockedPost, DetachedQuotePost, MissingPost, Post } from '../../models/posts.js'; 3 4 import { settings } from '../../models/settings.svelte.js'; 4 5
+1
src/components/posts/FeedPostParent.svelte
··· 1 1 <script lang="ts"> 2 + import { accountAPI, api } from '../../api.js'; 2 3 import { linkToPostById } from '../../router.js'; 3 4 import { atURI } from '../../utils.js'; 4 5
+1
src/components/posts/HiddenRepliesLink.svelte
··· 1 1 <script lang="ts"> 2 + import { api } from '../../api.js'; 2 3 import { showBiohazardDialog } from '../../skythread.js'; 3 4 import { settings } from '../../models/settings.svelte.js'; 4 5 import { parseThreadPost } from '../../models/posts.js';
+1
src/components/posts/LoadMoreLink.svelte
··· 1 1 <script lang="ts"> 2 + import { api } from '../../api.js'; 2 3 import { Post, parseThreadPost } from '../../models/posts.js'; 3 4 import { linkToPostThread } from '../../router.js'; 4 5 import { getPostContext } from './PostComponent.svelte';
+1
src/components/posts/PostFooter.svelte
··· 1 1 <script lang="ts"> 2 + import { accountAPI } from '../../api.js'; 2 3 import { getPostContext } from './PostComponent.svelte'; 3 4 import { linkToPostThread, linkToQuotesPage } from '../../router.js'; 4 5 import { account } from '../../models/account.svelte.js';
+1 -1
src/components/posts/ReferencedPostAuthorLink.svelte
··· 1 1 <script lang="ts"> 2 - import { Post } from '../../models/posts.js'; 2 + import { api } from '../../api.js'; 3 3 import { atURI } from '../../utils.js'; 4 4 5 5 let { post, status = undefined }: { post: AnyPost, status?: string | undefined } = $props();
+1
src/components/posts/ThreadRootParentRaw.svelte
··· 1 1 <script lang="ts"> 2 + import { api } from '../../api.js'; 2 3 import { linkToPostById } from '../../router.js'; 3 4 import { atURI } from '../../utils.js'; 4 5
+7 -10
src/models/account.svelte.ts
··· 1 - import { AuthenticatedAPI } from '../api/authenticated_api.js'; 1 + import { accountAPI, setAPI } from '../api.js'; 2 2 import { pdsEndpointForIdentifier } from '../api/identity.js'; 3 3 import { settings } from './settings.svelte.js'; 4 4 ··· 8 8 #avatarIsLoading: boolean; 9 9 10 10 constructor() { 11 - let accountAPI = new AuthenticatedAPI(); 12 - 13 11 this.#loggedIn = $state(accountAPI.isLoggedIn); 14 12 this.#avatarURL = $state(accountAPI.isLoggedIn ? accountAPI.user.avatar : undefined); 15 13 this.#avatarIsLoading = $state(false); ··· 36 34 return this.#avatarIsLoading; 37 35 } 38 36 39 - async logIn(identifier: string, password: string): Promise<AuthenticatedAPI> { 37 + async logIn(identifier: string, password: string) { 40 38 let pdsEndpoint = await pdsEndpointForIdentifier(identifier); 41 39 42 - let pdsAPI = new AuthenticatedAPI(pdsEndpoint); 43 - await pdsAPI.logIn(identifier, password); 40 + accountAPI.host = pdsEndpoint; 41 + await accountAPI.logIn(identifier, password); 44 42 45 43 this.#loggedIn = true; 46 44 this.#avatarIsLoading = true; 45 + setAPI(); 47 46 48 - pdsAPI.loadCurrentUserAvatar().then(url => { 47 + accountAPI.loadCurrentUserAvatar().then(url => { 49 48 this.#avatarURL = url || undefined; 50 49 }).catch(error => { 51 50 console.log(error); 52 51 }).finally(() => { 53 52 this.#avatarIsLoading = false; 54 53 }); 55 - 56 - return pdsAPI; 57 54 } 58 55 59 56 logOut() { 60 - window.accountAPI.resetTokens(); 57 + accountAPI.resetTokens(); 61 58 settings.logOut(); 62 59 location.reload(); 63 60 }
+1
src/models/posts.js
··· 1 + import { api } from '../api.js'; 1 2 import { atURI, castToInt } from '../utils.js'; 2 3 import { ATProtoRecord, FeedGeneratorRecord, StarterPackRecord, UserListRecord } from './records.js'; 3 4 import { Embed } from './embeds.js';
+1
src/pages/HashtagPage.svelte
··· 1 1 <script lang="ts"> 2 + import { api } from '../api.js'; 2 3 import { Post } from '../models/posts.js'; 3 4 import * as paginator from '../utils/paginator.js'; 4 5 import MainLoader from '../components/MainLoader.svelte';
+1
src/pages/NotificationsPage.svelte
··· 1 1 <script lang="ts"> 2 + import { accountAPI } from '../api.js'; 2 3 import { Post } from '../models/posts.js'; 3 4 import * as paginator from '../utils/paginator.js'; 4 5 import FeedPostParent from '../components/posts/FeedPostParent.svelte';
+1
src/pages/PostingStatsPage.svelte
··· 1 1 <script lang="ts"> 2 2 import UserAutocomplete, { type AutocompleteUser } from '../components/UserAutocomplete.svelte'; 3 3 import PostingStatsTable from '../components/PostingStatsTable.svelte'; 4 + import { accountAPI } from '../api.js'; 4 5 import { PostingStats, type PostingStatsResult } from '../services/posting_stats.js'; 5 6 import { numberOfDays } from '../utils.js'; 6 7
+1
src/pages/QuotesPage.svelte
··· 1 1 <script lang="ts"> 2 + import { api, blueAPI } from '../api.js'; 2 3 import { Post } from '../models/posts.js'; 3 4 import { showError } from '../utils.js'; 4 5 import * as paginator from '../utils/paginator.js';
+1
src/pages/ThreadPage.svelte
··· 1 1 <script lang="ts"> 2 + import { api, blueAPI } from '../api.js'; 2 3 import { Post, parseThreadPost } from '../models/posts.js'; 3 4 import { showError } from '../utils.js'; 4 5 import MainLoader from '../components/MainLoader.svelte';
+2 -2
src/services/like_stats.ts
··· 1 1 import { atURI, feedPostTime } from '../utils.js'; 2 - import { BlueskyAPI } from '../api.js'; 2 + import { BlueskyAPI, accountAPI } from '../api.js'; 3 3 4 4 export type LikeStatsResponse = { givenLikes: LikeStat[], receivedLikes: LikeStat[] } 5 5 export type LikeStat = { handle?: string, did?: string, avatar?: string, count: number } ··· 36 36 let givenStats = this.sumUpGivenLikes(givenLikes); 37 37 let topGiven = this.getTopEntries(givenStats); 38 38 39 - let profileInfo = await appView.getRequest('app.bsky.actor.getProfiles', { actors: topGiven.map(x => x.did) }); 39 + let profileInfo = await this.appView.getRequest('app.bsky.actor.getProfiles', { actors: topGiven.map(x => x.did) }); 40 40 41 41 for (let profile of profileInfo.profiles) { 42 42 let user = topGiven.find(x => x.did == profile.did)!;
+1 -1
src/services/lycan.ts
··· 1 1 import { Post } from '../models/posts.js'; 2 2 import * as paginator from '../utils/paginator.js'; 3 - import { BlueskyAPI } from '../api.js'; 3 + import { BlueskyAPI, accountAPI } from '../api.js'; 4 4 5 5 export type OnPostsLoaded = (data: { posts: Post[], terms: string[] }) => void 6 6 export type OnFinish = () => void
+1 -1
src/services/posting_stats.ts
··· 1 - import { BlueskyAPI } from '../api.js'; 1 + import { BlueskyAPI, accountAPI } from '../api.js'; 2 2 import { feedPostTime } from '../utils.js'; 3 3 4 4 /**
+1
src/services/timeline_search.ts
··· 1 + import { accountAPI } from '../api.js'; 1 2 import { Post, parseFeedPost } from '../models/posts.js'; 2 3 import { feedPostTime } from '../utils.js'; 3 4
+2 -10
src/skythread.js
··· 13 13 import ThreadPage from './pages/ThreadPage.svelte'; 14 14 15 15 import { $id } from './utils.js'; 16 - import { AuthenticatedAPI, BlueskyAPI } from './api.js'; 16 + import { BlueskyAPI, accountAPI } from './api.js'; 17 17 import { account } from './models/account.svelte.js'; 18 18 import { Lycan, DevLycan } from './services/lycan.js'; 19 19 ··· 42 42 hideDialog(dialog); 43 43 }); 44 44 } 45 - 46 - window.appView = new BlueskyAPI('api.bsky.app'); 47 - window.blueAPI = new BlueskyAPI('blue.mackuba.eu'); 48 - window.accountAPI = new AuthenticatedAPI(); 49 - window.api = (accountAPI.isLoggedIn && !account.isIncognito) ? accountAPI : appView; 50 45 51 46 parseQueryParams(); 52 47 } ··· 172 167 /** @param {string} identifier, @param {string} password, @returns {Promise<void>} */ 173 168 174 169 async function submitLogin(identifier, password) { 175 - let pds = await account.logIn(identifier, password); 176 - 177 - window.api = pds; 178 - window.accountAPI = pds; 170 + await account.logIn(identifier, password); 179 171 180 172 hideLoginDialog(); 181 173
-5
src/types.d.ts
··· 5 5 BlueskyAPI: typeof import("./api/bluesky_api.js").BlueskyAPI; 6 6 } 7 7 8 - declare var accountAPI: import("./api/authenticated_api.js").AuthenticatedAPI; 9 - declare var blueAPI: import("./api/bluesky_api.js").BlueskyAPI; 10 - declare var appView: import("./api/bluesky_api.js").BlueskyAPI; 11 - declare var api: import("./api/bluesky_api.js").BlueskyAPI; 12 - 13 8 type json = Record<string, any>; 14 9 15 10 type AnyPost = import("./models/posts.js").Post