initial profile implementation!
This commit is contained in:
		
							parent
							
								
									667b11f2f4
								
							
						
					
					
						commit
						449a11ee55
					
				
					 14 changed files with 212 additions and 57 deletions
				
			
		|  | @ -94,7 +94,9 @@ | ||||||
| 
 | 
 | ||||||
|         "posts": "Posts", |         "posts": "Posts", | ||||||
|         "replies": "Replies", |         "replies": "Replies", | ||||||
|         "media": "Media" |         "media": "Media", | ||||||
|  | 
 | ||||||
|  |         "loading": "loading profile..." | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     "logs": { |     "logs": { | ||||||
|  | @ -104,9 +106,12 @@ | ||||||
|         "no_hostname": "Attempted to connect to a server without providing a hostname", |         "no_hostname": "Attempted to connect to a server without providing a hostname", | ||||||
|         "no_https": "Cowardly refusing to connect to an insecure server", |         "no_https": "Cowardly refusing to connect to an insecure server", | ||||||
|         "connection_failed": "Failed to connect to %1", |         "connection_failed": "Failed to connect to %1", | ||||||
|         "post_fetch_failed": "Failed to fetch post %1", |         "post_fetch_failed": "Failed to fetch post", | ||||||
|  |         "post_fetch_failed_id": "Failed to fetch post %1", | ||||||
|         "post_parse_failed": "Failed to parse post", |         "post_parse_failed": "Failed to parse post", | ||||||
|         "post_parse_failed_id": "Failed to parse post %1", |         "post_parse_failed_id": "Failed to parse post %1", | ||||||
|  |         "profile_fetch_failed": "Failed to fetch profile", | ||||||
|  |         "profile_fetch_failed_id": "Failed to fetch profile %1", | ||||||
|         "token_revoke_failed": "Token revocation failed! Dumping data anyways", |         "token_revoke_failed": "Token revocation failed! Dumping data anyways", | ||||||
|         "sound_does_not_exist": "Attempted to play sound \"%1\", which does not exist!", |         "sound_does_not_exist": "Attempted to play sound \"%1\", which does not exist!", | ||||||
|         "account_data_empty": "Attempted to parse account data but no data was provided", |         "account_data_empty": "Attempted to parse account data but no data was provided", | ||||||
|  |  | ||||||
|  | @ -27,7 +27,12 @@ export function parseAccount(data) { | ||||||
|     account.username = data.username; |     account.username = data.username; | ||||||
|     account.name = account.nickname || account.username; |     account.name = account.nickname || account.username; | ||||||
|     account.avatar_url = data.avatar; |     account.avatar_url = data.avatar; | ||||||
|  |     account.banner_url = data.header; | ||||||
|     account.url = data.url; |     account.url = data.url; | ||||||
|  |     account.followers_count = data.followers_count; | ||||||
|  |     account.following_count = data.following_count; | ||||||
|  |     account.posts_count = data.statuses_count; | ||||||
|  |     account.bio = data.note; | ||||||
| 
 | 
 | ||||||
|     if (data.acct.includes('@')) |     if (data.acct.includes('@')) | ||||||
|         account.host = data.acct.split('@')[1]; |         account.host = data.acct.split('@')[1]; | ||||||
|  |  | ||||||
|  | @ -1,3 +1,7 @@ | ||||||
|  | const errors = { | ||||||
|  |     AUTHENTICATION_FAILED: "AUTHENTICATION_FAILED", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * GET /api/v1/instance |  * GET /api/v1/instance | ||||||
|  * @param {string} host - The domain of the target server. |  * @param {string} host - The domain of the target server. | ||||||
|  | @ -421,3 +425,26 @@ export async function getUser(host, token, user_id) { | ||||||
| 
 | 
 | ||||||
|     return data; |     return data; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * GET /api/v1/accounts/lookup?acct={handle} | ||||||
|  |  * @param {string} host - The domain of the target server. | ||||||
|  |  * @param {string} token - The application token. | ||||||
|  |  * @param {string} handle - The handle of the user to fetch. | ||||||
|  |  */ | ||||||
|  | export async function lookupUser(host, token, handle) { | ||||||
|  |     let url = `https://${host}/api/v1/accounts/lookup?acct=${handle}`; | ||||||
|  | 
 | ||||||
|  |     const res = await fetch(url, { | ||||||
|  |         method: 'GET', | ||||||
|  |         headers: { "Authorization": token ? `Bearer ${token}` : null } | ||||||
|  |     }); | ||||||
|  |     if (!res.ok) { | ||||||
|  |         const json = await res.json(); | ||||||
|  |         if (json.error = errors.AUTHENTICATION_FAILED) | ||||||
|  |             throw new Error("This method requires authentication"); | ||||||
|  |     } | ||||||
|  |     const data = await res.json(); | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,9 @@ import * as api from '$lib/api.js'; | ||||||
| import { writable } from 'svelte/store'; | import { writable } from 'svelte/store'; | ||||||
| import { app_name } from '$lib/config.js'; | import { app_name } from '$lib/config.js'; | ||||||
| import { browser } from "$app/environment"; | import { browser } from "$app/environment"; | ||||||
|  | import Lang from '$lib/lang'; | ||||||
|  | 
 | ||||||
|  | const lang = Lang('en_GB'); | ||||||
| 
 | 
 | ||||||
| const server_types = { | const server_types = { | ||||||
|     UNSUPPORTED: "unsupported", |     UNSUPPORTED: "unsupported", | ||||||
|  |  | ||||||
|  | @ -18,9 +18,21 @@ | ||||||
|     function click() { |     function click() { | ||||||
|         if (disabled) return; |         if (disabled) return; | ||||||
|         if (href) { |         if (href) { | ||||||
|             location = href; |             const link = document.createElement('a'); | ||||||
|  |             link.href = href; | ||||||
|  |             link.dispatchEvent(new MouseEvent('click', { | ||||||
|  |                 bubbles: true, | ||||||
|  |                 cancelable: true, | ||||||
|  |                 view: window, | ||||||
|  |                 ctrlKey: event.ctrlKey, | ||||||
|  |                 metaKey: event.metaKey, | ||||||
|  |                 shiftKey: event.shiftKey, | ||||||
|  |                 altKey: event.altKey, | ||||||
|  |                 button: event.button, | ||||||
|  |             })); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         playSound(sound); |         playSound(sound); | ||||||
|         dispatch('click'); |         dispatch('click'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -90,7 +90,8 @@ | ||||||
| 
 | 
 | ||||||
| <div class="composer"> | <div class="composer"> | ||||||
|     <div class="composer-header-container"> |     <div class="composer-header-container"> | ||||||
|         <a href={$account.url} target="_blank" class="composer-avatar-container" on:mouseup|stopPropagation> |         <!-- TODO: account switcher in composer --> | ||||||
|  |         <a href="" class="composer-avatar-container" on:mouseup|stopPropagation> | ||||||
|             <img src={$account.avatar_url} type={$account.avatar_type} alt="" width="48" height="48" class="composer-avatar" loading="lazy" decoding="async"> |             <img src={$account.avatar_url} type={$account.avatar_type} alt="" width="48" height="48" class="composer-avatar" loading="lazy" decoding="async"> | ||||||
|         </a> |         </a> | ||||||
|         <header class="composer-header"> |         <header class="composer-header"> | ||||||
|  |  | ||||||
|  | @ -61,6 +61,16 @@ | ||||||
|         goto(route); |         goto(route); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     function gotoProfile() { | ||||||
|  |         if (!$account) return; | ||||||
|  |         playSound(); | ||||||
|  |         window.scrollTo({ | ||||||
|  |             top: 0, | ||||||
|  |             behavior: "smooth" | ||||||
|  |         }); | ||||||
|  |         goto(`/${$server.host}/${$account.username}`); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     async function log_out() { |     async function log_out() { | ||||||
|         if (!confirm("This will log you out. Are you sure?")) return; |         if (!confirm("This will log you out. Are you sure?")) return; | ||||||
|          |          | ||||||
|  | @ -171,9 +181,9 @@ | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div id="account-button"> |         <div id="account-button"> | ||||||
|             <img src={$account.avatar_url} class="account-avatar" height="64px" alt="" aria-hidden="true" on:click={() => playSound()}> |             <img src={$account.avatar_url} class="account-avatar" height="64px" alt="" aria-hidden="true" on:click={() => gotoProfile()}> | ||||||
|             <div class="account-name" aria-hidden="true"> |             <div class="account-name" aria-hidden="true"> | ||||||
|                 <a href={$account.url} class="nickname" title={$account.nickname}>{@html $account.rich_name}</a> |                 <a href="/{$server.host}/{$account.username}" class="nickname" title={$account.nickname}>{@html $account.rich_name}</a> | ||||||
|                 <span class="username" title={`@${$account.username}@${$account.host}`}> |                 <span class="username" title={`@${$account.username}@${$account.host}`}> | ||||||
|                     {$account.fqn} |                     {$account.fqn} | ||||||
|                 </span> |                 </span> | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| <script> | <script> | ||||||
|     import { shorthand as short_time } from '$lib/time.js'; |     import { shorthand as short_time } from '$lib/time.js'; | ||||||
|  |     import { server } from '$lib/client/server'; | ||||||
|     import Lang from '$lib/lang'; |     import Lang from '$lib/lang'; | ||||||
| 
 | 
 | ||||||
|     const lang = Lang('en_GB'); |     const lang = Lang('en_GB'); | ||||||
|  | @ -14,7 +15,7 @@ | ||||||
|     <span class="post-context-action"> |     <span class="post-context-action"> | ||||||
|         { @html |         { @html | ||||||
|         lang.string('post.boosted', |         lang.string('post.boosted', | ||||||
|         `<a href={${post.account.url}} target="_blank"><span class="name">${post.account.rich_name}</span></a>`) |         `<a href="/${$server.host}/${post.account.fqn}"><span class="name">${post.account.rich_name}</span></a>`) | ||||||
|         } |         } | ||||||
|     </span> |     </span> | ||||||
|     <span class="post-context-time"> |     <span class="post-context-time"> | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| <script> | <script> | ||||||
|     import { shorthand as short_time } from '$lib/time.js'; |     import { shorthand as short_time } from '$lib/time.js'; | ||||||
|  |     import { server } from '$lib/client/server'; | ||||||
|     import Lang from '$lib/lang'; |     import Lang from '$lib/lang'; | ||||||
| 
 | 
 | ||||||
|     const lang = Lang('en_GB'); |     const lang = Lang('en_GB'); | ||||||
|  | @ -11,12 +12,12 @@ | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <div class={"post-header-container" + (reply ? " reply" : "")}> | <div class={"post-header-container" + (reply ? " reply" : "")}> | ||||||
|     <a href={post.account.url} target="_blank" class="post-avatar-container" on:mouseup|stopPropagation> |     <a href="/{$server.host}/{post.account.fqn}" class="post-avatar-container" on:mouseup|stopPropagation> | ||||||
|         <img src={post.account.avatar_url} type={post.account.avatar_type} alt="" width="48" height="48" class="post-avatar" loading="lazy" decoding="async"> |         <img src={post.account.avatar_url} type={post.account.avatar_type} alt="" width="48" height="48" class="post-avatar" loading="lazy" decoding="async"> | ||||||
|     </a> |     </a> | ||||||
|     <header class="post-header"> |     <header class="post-header"> | ||||||
|         <div class="post-user-info" on:mouseup|stopPropagation> |         <div class="post-user-info" on:mouseup|stopPropagation> | ||||||
|             <a href={post.account.url} target="_blank" class="name">{@html post.account.rich_name}</a> |             <a href="/{$server.host}/{post.account.fqn}" class="name">{@html post.account.rich_name}</a> | ||||||
|             <span class="username">{post.account.mention}</span> |             <span class="username">{post.account.mention}</span> | ||||||
|         </div> |         </div> | ||||||
|         <div class="post-info" on:mouseup|stopPropagation> |         <div class="post-info" on:mouseup|stopPropagation> | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| export async function load({ params }) { | export async function load({ params }) { | ||||||
|     return { |     return { | ||||||
|         server_domain: params.server |         server_host: params.server | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/routes/[server]/[account]/+page.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/routes/[server]/[account]/+page.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | export async function load({ params }) { | ||||||
|  |     let handle = params.account; | ||||||
|  |     if (handle.startsWith('@')) | ||||||
|  |         handle = handle.substring(1); | ||||||
|  | 
 | ||||||
|  |     return { | ||||||
|  |         server_host: params.server, | ||||||
|  |         account_handle: handle, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | @ -3,45 +3,86 @@ | ||||||
|     import HomeIcon from '@cf/icons/unlisted.svg'; |     import HomeIcon from '@cf/icons/unlisted.svg'; | ||||||
|     import MoreIcon from '@cf/icons/more.svg'; |     import MoreIcon from '@cf/icons/more.svg'; | ||||||
|     import Lang from '$lib/lang'; |     import Lang from '$lib/lang'; | ||||||
|  |     import * as api from '$lib/api.js'; | ||||||
|  |     import { server, createServer } from '$lib/client/server.js'; | ||||||
|  |     import { app } from '$lib/client/app.js'; | ||||||
|  |     import { parseAccount } from '$lib/account.js'; | ||||||
|  |     import { account } from '$lib/stores/account'; | ||||||
|  |     import { goto, afterNavigate } from '$app/navigation'; | ||||||
|  |     import { base } from '$app/paths'; | ||||||
|  | 
 | ||||||
|  |     export let data; | ||||||
| 
 | 
 | ||||||
|     const lang = Lang('en_GB'); |     const lang = Lang('en_GB'); | ||||||
|  | 
 | ||||||
|  |     let profile = fetchProfile(data.account_handle); | ||||||
|  |     let error = false; | ||||||
|  |     let previous_page = base; | ||||||
|  | 
 | ||||||
|  |     afterNavigate(({from}) => { | ||||||
|  |         previous_page = from?.url.pathname || previous_page; | ||||||
|  |         profile = fetchProfile(data.account_handle); | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     async function fetchProfile(handle) { | ||||||
|  |         let token = $app ? $app.token : null; | ||||||
|  | 
 | ||||||
|  |         if (!$server || $server.host !== data.server_host) { | ||||||
|  |             server.set(await createServer(data.server_host)); | ||||||
|  |             if (!$server) { | ||||||
|  |                 error = lang.string('error.connection_failed', data.server_host); | ||||||
|  |                 throw new Error(lang.string('logs.connection_failed', data.server_host)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let profile_data; | ||||||
|  |         try { | ||||||
|  |             profile_data = await api.lookupUser($server.host, token, handle); | ||||||
|  |             console.debug(profile_data); | ||||||
|  |         } catch (error) { | ||||||
|  |             throw error; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!profile_data || profile_data.error) { | ||||||
|  |             error = lang.string('error.profile_fetch_failed_id', handle); | ||||||
|  |             throw new Error(lang.string('logs.profile_fetch_failed_id', handle)); | ||||||
|  |         } | ||||||
|  |         let profile = await parseAccount(profile_data, 0); | ||||||
|  | 
 | ||||||
|  |         return profile; | ||||||
|  |     } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <header> | {#await profile} | ||||||
|  |     <div class="loading throb"> | ||||||
|  |         <span>{lang.string('profile.loading')}</span> | ||||||
|  |     </div> | ||||||
|  | {:then profile} | ||||||
|  |     <header data-banner="{profile.banner_url}"> | ||||||
|  |         <img src="{profile.banner_url}" class="profile-banner" alt=""> | ||||||
|         <div class="profile-tag"> |         <div class="profile-tag"> | ||||||
|             <!-- svelte-ignore a11y-img-redundant-alt --> |             <!-- svelte-ignore a11y-img-redundant-alt --> | ||||||
|         <img src="https://f.mae.wtf/proxy/avatar.webp?url=https%3A%2F%2Ff.mae.wtf%2Ffiles%2F9cf9f3f1-70f6-4ecc-be2b-34ae6588bbdc&avatar=1" alt="Profile picture"> |             <img src="{profile.avatar_url}" alt=""> | ||||||
|             <div class="profile-tag-names"> |             <div class="profile-tag-names"> | ||||||
|             <h1>mae</h1> |                 <h1>{@html profile.rich_name}</h1> | ||||||
|             <p>mae@f.mae.wtf</p> |                 <p>{profile.fqn}</p> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
| </header> |     </header> | ||||||
| <div class="profile-info"> |     <div class="profile-info"> | ||||||
|     <div> |         <p class="profile-bio">{@html profile.bio}</p> | ||||||
|         <p class="profile-bio"> |         <ul class="profile-counts"> | ||||||
| music maker and coder! |             <li><b>{lang.string('profile.followers')}</b> {profile.followers_count}</li> | ||||||
| she/they/it - 18 - 🏳️⚧️🇬🇧 |             <li><b>{lang.string('profile.following')}</b> {profile.following_count}</li> | ||||||
| robotgirl in training |             <li><b>{lang.string('profile.posts')}</b> {profile.posts_count}</li> | ||||||
| 
 |         </ul> | ||||||
| feel free to follow req if ur cool |  | ||||||
| 
 |  | ||||||
| https://mae.wtf/ |  | ||||||
| also <a href="" class="mention">@mae</a> |  | ||||||
| 
 |  | ||||||
| "solid 7.5/10 motherliness rating" - <a href="" class="mention">@ellie</a> |  | ||||||
|         </p> |  | ||||||
|         <p class="profile-counts"> |  | ||||||
|             <span> |  | ||||||
|                 <b>{lang.string('profile.followers')}</b>   1225 |  | ||||||
|             </span> |  | ||||||
|             <span> |  | ||||||
|                 <b>{lang.string('profile.following')}</b>   1345 |  | ||||||
|             </span> |  | ||||||
|         </p> |  | ||||||
|         <div class="profile-actions"> |         <div class="profile-actions"> | ||||||
|             <Button label="{lang.string('profile.follow')}" class="profile-btn-follow">{lang.string('profile.follow')}</Button> |             {#if $account && profile.fqn !== $account.fqn} | ||||||
|             <Button label="{lang.string('profile.home_instance')}"> |             <Button disabled filled label="{lang.string('profile.follow')} {profile.nickname}" class="profile-btn-follow"> | ||||||
|  |                 {lang.string('profile.follow')} | ||||||
|  |             </Button> | ||||||
|  |             {/if} | ||||||
|  |             <Button label="{lang.string('profile.home_instance')}" href="{profile.url}"> | ||||||
|                 <HomeIcon width="24px"/> |                 <HomeIcon width="24px"/> | ||||||
|             </Button> |             </Button> | ||||||
|             <Button> |             <Button> | ||||||
|  | @ -49,25 +90,37 @@ also <a href="" class="mention">@mae</a> | ||||||
|             </Button> |             </Button> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
| </div> |  | ||||||
| 
 | 
 | ||||||
| <div class="profile-post-categories"> |     <div class="profile-post-categories"> | ||||||
|     <Button active>{lang.string('profile.posts')}</Button> |         <Button active> | ||||||
|     <Button>{lang.string('profile.replies')}</Button> |             {lang.string('profile.posts')} | ||||||
|     <Button>{lang.string('profile.media')}</Button> |         </Button> | ||||||
| </div> |         <Button> | ||||||
|  |             {lang.string('profile.replies')} | ||||||
|  |         </Button> | ||||||
|  |         <Button> | ||||||
|  |             {lang.string('profile.media')} | ||||||
|  |         </Button> | ||||||
|  |     </div> | ||||||
|  | {:catch error} | ||||||
|  |     <p class="error">{error}</p> | ||||||
|  | {/await} | ||||||
| 
 | 
 | ||||||
| <style> | <style> | ||||||
|     header { |     header { | ||||||
|         margin-top: 1rem; |         margin-top: 1rem; | ||||||
|         width: 100%; |         width: 100%; | ||||||
|         height: 215px; |         height: 215px; | ||||||
|         background-image: url("https://f.mae.wtf/files/42bcf2ba-4256-4d22-b22f-019dfb2c0008.webp"); |  | ||||||
|         background-position: center; |  | ||||||
|         background-size: cover; |  | ||||||
|         position: relative; |         position: relative; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     .profile-banner { | ||||||
|  |         width: 100%; | ||||||
|  |         height: 100%; | ||||||
|  |         object-fit: cover; | ||||||
|  |         background-color: var(--bg-700); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     .profile-tag { |     .profile-tag { | ||||||
|         position: absolute; |         position: absolute; | ||||||
|         bottom: 16px; |         bottom: 16px; | ||||||
|  | @ -112,7 +165,16 @@ also <a href="" class="mention">@mae</a> | ||||||
|         /* !! may not be required in prod */ |         /* !! may not be required in prod */ | ||||||
|         white-space: pre-line; |         white-space: pre-line; | ||||||
|     } |     } | ||||||
|  |     :global(.profile-bio p:first-of-type) { | ||||||
|  |         margin: 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     .profile-counts { | ||||||
|  |         padding: 0; | ||||||
|  |     } | ||||||
|  |     .profile-counts li { | ||||||
|  |         display: inline-block; | ||||||
|  |     } | ||||||
|     .profile-counts > *:not(.profile-counts:first-child) { |     .profile-counts > *:not(.profile-counts:first-child) { | ||||||
|         margin-right: 16px; |         margin-right: 16px; | ||||||
|     } |     } | ||||||
|  | @ -124,10 +186,8 @@ also <a href="" class="mention">@mae</a> | ||||||
|         gap: .5rem; |         gap: .5rem; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .profile-actions :global(button:first-child) { |     .profile-btn-follow { | ||||||
|         padding: 0 32px; |         padding: 0 32px; | ||||||
|         background-color: var(--accent); |  | ||||||
|         color: var(--bg-900); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .profile-actions :global(button) { |     .profile-actions :global(button) { | ||||||
|  | @ -140,4 +200,20 @@ also <a href="" class="mention">@mae</a> | ||||||
|         padding: 1rem 0; |         padding: 1rem 0; | ||||||
|         gap: 1rem; |         gap: 1rem; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     .loading { | ||||||
|  |         width: 100%; | ||||||
|  |         height: 80vh; | ||||||
|  |         display: flex; | ||||||
|  |         justify-content: center; | ||||||
|  |         align-items: center; | ||||||
|  |         font-size: 2em; | ||||||
|  |         font-weight: bold; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .error { | ||||||
|  |         padding: 4em 0; | ||||||
|  |         width: 100%; | ||||||
|  |         text-align: center; | ||||||
|  |     } | ||||||
| </style> | </style> | ||||||
|  |  | ||||||
|  | @ -1,4 +1,8 @@ | ||||||
| export async function load({ params }) { | export async function load({ params }) { | ||||||
|  |     let handle = params.account; | ||||||
|  |     if (handle.startsWith('@')) | ||||||
|  |         handle = handle.substring(1); | ||||||
|  | 
 | ||||||
|     return { |     return { | ||||||
|         server_host: params.server, |         server_host: params.server, | ||||||
|         account_handle: params.account, |         account_handle: params.account, | ||||||
|  |  | ||||||
|  | @ -41,8 +41,8 @@ | ||||||
| 
 | 
 | ||||||
|         const post_data = await api.getPost($server.host, token, post_id); |         const post_data = await api.getPost($server.host, token, post_id); | ||||||
|         if (!post_data || post_data.error) { |         if (!post_data || post_data.error) { | ||||||
|             error = lang.string('error.post_fetch_failed', post_id); |             error = lang.string('error.post_fetch_failed_id', post_id); | ||||||
|             console.error(lang.string('logs.post_fetch_failed', post_id)); |             console.error(lang.string('logs.post_fetch_failed_id', post_id)); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         let post = await parsePost(post_data, 0); |         let post = await parsePost(post_data, 0); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue