initial profile implementation!

This commit is contained in:
ari melody 2025-07-14 00:19:42 +01:00
parent 667b11f2f4
commit 449a11ee55
Signed by: ari
GPG key ID: CF99829C92678188
14 changed files with 212 additions and 57 deletions

View file

@ -1,5 +1,5 @@
export async function load({ params }) {
return {
server_domain: params.server
server_host: params.server
};
}

View 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,
};
}

View file

@ -3,45 +3,86 @@
import HomeIcon from '@cf/icons/unlisted.svg';
import MoreIcon from '@cf/icons/more.svg';
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');
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>
<header>
<div class="profile-tag">
<!-- 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">
<div class="profile-tag-names">
<h1>mae</h1>
<p>mae@f.mae.wtf</p>
</div>
{#await profile}
<div class="loading throb">
<span>{lang.string('profile.loading')}</span>
</div>
</header>
<div class="profile-info">
<div>
<p class="profile-bio">
music maker and coder!
she/they/it - 18 - 🏳️‍⚧️🇬🇧
robotgirl in training
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>
{:then profile}
<header data-banner="{profile.banner_url}">
<img src="{profile.banner_url}" class="profile-banner" alt="">
<div class="profile-tag">
<!-- svelte-ignore a11y-img-redundant-alt -->
<img src="{profile.avatar_url}" alt="">
<div class="profile-tag-names">
<h1>{@html profile.rich_name}</h1>
<p>{profile.fqn}</p>
</div>
</div>
</header>
<div class="profile-info">
<p class="profile-bio">{@html profile.bio}</p>
<ul class="profile-counts">
<li><b>{lang.string('profile.followers')}</b> {profile.followers_count}</li>
<li><b>{lang.string('profile.following')}</b> {profile.following_count}</li>
<li><b>{lang.string('profile.posts')}</b> {profile.posts_count}</li>
</ul>
<div class="profile-actions">
<Button label="{lang.string('profile.follow')}" class="profile-btn-follow">{lang.string('profile.follow')}</Button>
<Button label="{lang.string('profile.home_instance')}">
{#if $account && profile.fqn !== $account.fqn}
<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"/>
</Button>
<Button>
@ -49,25 +90,37 @@ also <a href="" class="mention">@mae</a>
</Button>
</div>
</div>
</div>
<div class="profile-post-categories">
<Button active>{lang.string('profile.posts')}</Button>
<Button>{lang.string('profile.replies')}</Button>
<Button>{lang.string('profile.media')}</Button>
</div>
<div class="profile-post-categories">
<Button active>
{lang.string('profile.posts')}
</Button>
<Button>
{lang.string('profile.replies')}
</Button>
<Button>
{lang.string('profile.media')}
</Button>
</div>
{:catch error}
<p class="error">{error}</p>
{/await}
<style>
header {
margin-top: 1rem;
width: 100%;
height: 215px;
background-image: url("https://f.mae.wtf/files/42bcf2ba-4256-4d22-b22f-019dfb2c0008.webp");
background-position: center;
background-size: cover;
position: relative;
}
.profile-banner {
width: 100%;
height: 100%;
object-fit: cover;
background-color: var(--bg-700);
}
.profile-tag {
position: absolute;
bottom: 16px;
@ -112,7 +165,16 @@ also <a href="" class="mention">@mae</a>
/* !! may not be required in prod */
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) {
margin-right: 16px;
}
@ -124,10 +186,8 @@ also <a href="" class="mention">@mae</a>
gap: .5rem;
}
.profile-actions :global(button:first-child) {
.profile-btn-follow {
padding: 0 32px;
background-color: var(--accent);
color: var(--bg-900);
}
.profile-actions :global(button) {
@ -140,4 +200,20 @@ also <a href="" class="mention">@mae</a>
padding: 1rem 0;
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>

View file

@ -1,4 +1,8 @@
export async function load({ params }) {
let handle = params.account;
if (handle.startsWith('@'))
handle = handle.substring(1);
return {
server_host: params.server,
account_handle: params.account,

View file

@ -41,8 +41,8 @@
const post_data = await api.getPost($server.host, token, post_id);
if (!post_data || post_data.error) {
error = lang.string('error.post_fetch_failed', post_id);
console.error(lang.string('logs.post_fetch_failed', post_id));
error = lang.string('error.post_fetch_failed_id', post_id);
console.error(lang.string('logs.post_fetch_failed_id', post_id));
return;
}
let post = await parsePost(post_data, 0);