2025-04-08 15:49:41 -04:00
|
|
|
{% extends "root.html" %} {% block head %}
|
2025-03-25 23:58:27 -04:00
|
|
|
<title>{{ profile.username }} - {{ config.name }}</title>
|
2025-04-09 00:10:58 -04:00
|
|
|
|
|
|
|
<meta name="og:title" content="{{ profile.username }}" />
|
|
|
|
<meta
|
|
|
|
name="description"
|
|
|
|
content="View @{{ profile.username }}'s profile on {{ config.name }}!"
|
|
|
|
/>
|
|
|
|
<meta
|
|
|
|
name="og:description"
|
|
|
|
content="View @{{ profile.username }}'s profile on {{ config.name }}!"
|
|
|
|
/>
|
|
|
|
|
|
|
|
<meta property="og:type" content="profile" />
|
|
|
|
<meta property="profile:username" content="{{ profile.username }}" />
|
|
|
|
|
|
|
|
<meta
|
|
|
|
name="og:image"
|
|
|
|
content="{{ config.host|safe }}/api/v1/auth/user/{{ profile.username }}/avatar?selector_type=username"
|
|
|
|
/>
|
|
|
|
|
|
|
|
<meta
|
|
|
|
name="twitter:image"
|
|
|
|
content="{{ config.host|safe }}/api/v1/auth/user/{{ profile.username }}/avatar?selector_type=username"
|
|
|
|
/>
|
|
|
|
|
|
|
|
<meta name="twitter:card" content="summary" />
|
|
|
|
<meta name="twitter:title" content="{{ profile.username }}" />
|
|
|
|
<meta
|
|
|
|
name="twitter:description"
|
|
|
|
content="View @{{ profile.username }}'s profile on {{ config.name }}!"
|
|
|
|
/>
|
2025-03-25 23:58:27 -04:00
|
|
|
{% endblock %} {% block body %} {{ macros::nav() }}
|
|
|
|
<article>
|
2025-03-31 19:31:36 -04:00
|
|
|
<div class="content_container flex flex-col gap-4">
|
|
|
|
{{ components::banner(username=profile.username) }}
|
|
|
|
|
2025-03-25 23:58:27 -04:00
|
|
|
<div class="w-full flex gap-4 flex-collapse">
|
|
|
|
<div
|
|
|
|
class="lhs flex flex-col gap-2 sm:w-full"
|
2025-04-09 19:25:41 -04:00
|
|
|
style="width: 22rem; min-width: 22rem"
|
2025-03-25 23:58:27 -04:00
|
|
|
>
|
|
|
|
<div class="card-nest w-full">
|
|
|
|
<div class="card flex gap-2" id="user_avatar_and_name">
|
2025-03-29 00:26:56 -04:00
|
|
|
{{
|
|
|
|
components::avatar(username=profile.username,size="72px")
|
2025-03-25 23:58:27 -04:00
|
|
|
}}
|
|
|
|
<div class="flex flex-col">
|
2025-03-26 21:46:21 -04:00
|
|
|
<!-- prettier-ignore -->
|
2025-04-01 16:12:13 -04:00
|
|
|
<h3 id="username" class="username flex items-center gap-2">
|
2025-04-03 17:42:03 -04:00
|
|
|
<span class="name shorter">{{ components::username(user=profile) }}</span>
|
2025-03-26 21:46:21 -04:00
|
|
|
|
|
|
|
{% if profile.is_verified %}
|
2025-04-01 16:12:13 -04:00
|
|
|
<span title="Verified" style="color: var(--color-primary);" class="flex items-center">
|
2025-03-26 21:46:21 -04:00
|
|
|
{{ icon "badge-check" }}
|
|
|
|
</span>
|
|
|
|
{% endif %}
|
2025-04-06 13:43:12 -04:00
|
|
|
|
|
|
|
{% if is_supporter %}
|
|
|
|
<span title="Supporter" style="color: var(--color-primary);" class="flex items-center">
|
|
|
|
{{ icon "star" }}
|
|
|
|
</span>
|
|
|
|
{% endif %}
|
2025-03-25 23:58:27 -04:00
|
|
|
</h3>
|
|
|
|
|
|
|
|
<span class="fade">{{ profile.username }}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-04-10 18:16:52 -04:00
|
|
|
<div
|
|
|
|
class="card flex flex-col items-center gap-2"
|
|
|
|
id="social"
|
|
|
|
>
|
2025-03-31 20:02:09 -04:00
|
|
|
<div class="w-full flex">
|
|
|
|
<a
|
2025-03-31 22:35:11 -04:00
|
|
|
href="/@{{ profile.username }}/followers"
|
2025-03-31 20:02:09 -04:00
|
|
|
class="w-full flex justify-center items-center gap-2"
|
|
|
|
>
|
|
|
|
<h4>{{ profile.follower_count }}</h4>
|
|
|
|
<span>{{ text "auth:label.followers" }}</span>
|
|
|
|
</a>
|
|
|
|
<a
|
2025-03-31 22:35:11 -04:00
|
|
|
href="/@{{ profile.username }}/following"
|
2025-03-31 20:02:09 -04:00
|
|
|
class="w-full flex justify-center items-center gap-2"
|
|
|
|
>
|
|
|
|
<h4>{{ profile.following_count }}</h4>
|
|
|
|
<span>{{ text "auth:label.following" }}</span>
|
|
|
|
</a>
|
|
|
|
</div>
|
2025-04-10 18:16:52 -04:00
|
|
|
|
|
|
|
{% if is_following_you %}
|
|
|
|
<b
|
|
|
|
class="notification chip w-content flex items-center gap-2"
|
|
|
|
>
|
|
|
|
{{ icon "heart" }}
|
|
|
|
<span>Follows you</span>
|
|
|
|
</b>
|
|
|
|
{% endif %}
|
2025-03-25 23:58:27 -04:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="card-nest flex flex-col">
|
2025-04-09 19:52:36 -04:00
|
|
|
<div id="bio" class="card small no_p_margin">
|
2025-03-29 22:27:57 -04:00
|
|
|
{{ profile.settings.biography|markdown|safe }}
|
2025-03-25 23:58:27 -04:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="card flex flex-col gap-2">
|
2025-04-26 16:27:18 -04:00
|
|
|
<!-- prettier-ignore -->
|
|
|
|
<div style="display: contents;">
|
|
|
|
{% if profile.connections.Spotify and profile.connections.Spotify[0].data.name and profile.connections.Spotify[0].show_on_profile %}
|
|
|
|
{{ components::spotify_playing(state=profile.connections.Spotify[1]) }}
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
|
2025-03-25 23:58:27 -04:00
|
|
|
<div class="w-full flex justify-between items-center">
|
|
|
|
<span class="notification chip">ID</span>
|
|
|
|
<button
|
|
|
|
title="Copy"
|
2025-03-31 15:39:49 -04:00
|
|
|
onclick="trigger('atto::copy_text', ['{{ profile.id }}'])"
|
2025-03-25 23:58:27 -04:00
|
|
|
class="camo small"
|
|
|
|
>
|
|
|
|
{{ icon "copy" }}
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="w-full flex justify-between items-center">
|
|
|
|
<span class="notification chip">Joined</span>
|
|
|
|
<span class="date">{{ profile.created }}</span>
|
|
|
|
</div>
|
2025-04-02 14:11:01 -04:00
|
|
|
|
2025-04-12 22:25:54 -04:00
|
|
|
<div class="w-full flex justify-between items-center">
|
|
|
|
<span class="notification chip">Posts</span>
|
|
|
|
<span>{{ profile.post_count }}</span>
|
|
|
|
</div>
|
|
|
|
|
2025-04-02 14:11:01 -04:00
|
|
|
{% if not profile.settings.private_last_seen or is_self
|
|
|
|
or is_helper %}
|
|
|
|
<div class="w-full flex justify-between items-center">
|
|
|
|
<span class="notification chip">Last seen</span>
|
2025-04-02 14:19:37 -04:00
|
|
|
|
|
|
|
<div class="flex">
|
|
|
|
{{ components::online_indicator(user=profile) }}
|
|
|
|
<span class="date">
|
|
|
|
{{ profile.last_seen }}
|
|
|
|
</span>
|
|
|
|
</div>
|
2025-04-02 14:11:01 -04:00
|
|
|
</div>
|
|
|
|
{% endif %}
|
2025-03-25 23:58:27 -04:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-04-01 15:03:56 -04:00
|
|
|
{% if not is_self and user %}
|
2025-03-31 20:02:09 -04:00
|
|
|
<div class="card-nest">
|
|
|
|
<div class="card small">
|
|
|
|
<b>{{ text "auth:label.relationship" }}</b>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="card flex gap-2 flex-wrap">
|
2025-04-11 18:08:51 -04:00
|
|
|
{% if not is_blocking %}
|
|
|
|
<button
|
|
|
|
onclick="toggle_follow_user(event)"
|
|
|
|
class="{% if is_following %} hidden{% endif %}"
|
|
|
|
atto_tag="user.follow"
|
|
|
|
>
|
2025-03-31 20:02:09 -04:00
|
|
|
{{ icon "user-plus" }}
|
2025-04-19 18:59:55 -04:00
|
|
|
<span>{{ text "auth:action.follow" }}</span>
|
2025-03-31 20:02:09 -04:00
|
|
|
</button>
|
2025-04-11 18:08:51 -04:00
|
|
|
|
2025-03-31 20:02:09 -04:00
|
|
|
<button
|
2025-04-11 18:08:51 -04:00
|
|
|
onclick="toggle_follow_user(event)"
|
|
|
|
class="quaternary red{% if not is_following %} hidden{% endif %}"
|
|
|
|
atto_tag="user.unfollow"
|
2025-03-31 20:02:09 -04:00
|
|
|
>
|
|
|
|
{{ icon "user-minus" }}
|
2025-04-19 18:59:55 -04:00
|
|
|
<span>{{ text "auth:action.unfollow" }}</span>
|
2025-03-31 20:02:09 -04:00
|
|
|
</button>
|
|
|
|
|
|
|
|
<button
|
|
|
|
onclick="toggle_block_user()"
|
|
|
|
class="quaternary red"
|
|
|
|
>
|
|
|
|
{{ icon "shield" }}
|
2025-04-19 18:59:55 -04:00
|
|
|
<span>{{ text "auth:action.block" }}</span>
|
2025-03-31 20:02:09 -04:00
|
|
|
</button>
|
|
|
|
{% else %}
|
|
|
|
<button
|
|
|
|
onclick="toggle_block_user()"
|
|
|
|
class="quaternary red"
|
|
|
|
>
|
|
|
|
{{ icon "shield-off" }}
|
2025-04-19 18:59:55 -04:00
|
|
|
<span>{{ text "auth:action.unblock" }}</span>
|
2025-03-31 20:02:09 -04:00
|
|
|
</button>
|
2025-04-06 13:43:12 -04:00
|
|
|
{% endif %} {% if is_helper %}
|
|
|
|
<a
|
|
|
|
href="/mod_panel/profile/{{ profile.id }}"
|
|
|
|
class="button quaternary"
|
|
|
|
>
|
|
|
|
{{ icon "shield" }}
|
|
|
|
<span>{{ text "general:action.manage" }}</span>
|
|
|
|
</a>
|
2025-03-31 20:02:09 -04:00
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
<script>
|
2025-04-11 18:08:51 -04:00
|
|
|
globalThis.toggle_follow_user = async (e) => {
|
|
|
|
await trigger("atto::debounce", [
|
|
|
|
"users::follow",
|
|
|
|
]);
|
|
|
|
|
2025-03-31 20:02:09 -04:00
|
|
|
fetch(
|
2025-04-04 21:42:08 -04:00
|
|
|
"/api/v1/auth/user/{{ profile.id }}/follow",
|
2025-03-31 20:02:09 -04:00
|
|
|
{
|
|
|
|
method: "POST",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.then((res) => res.json())
|
|
|
|
.then((res) => {
|
|
|
|
trigger("atto::toast", [
|
|
|
|
res.ok ? "success" : "error",
|
|
|
|
res.message,
|
|
|
|
]);
|
2025-04-11 18:08:51 -04:00
|
|
|
|
|
|
|
if (
|
|
|
|
e.target.getAttribute(
|
|
|
|
"atto_tag",
|
|
|
|
) === "user.follow"
|
|
|
|
) {
|
|
|
|
document
|
|
|
|
.querySelector(
|
|
|
|
'[atto_tag="user.follow"]',
|
|
|
|
)
|
|
|
|
.classList.add("hidden");
|
|
|
|
document
|
|
|
|
.querySelector(
|
|
|
|
'[atto_tag="user.unfollow"]',
|
|
|
|
)
|
|
|
|
.classList.remove("hidden");
|
|
|
|
} else {
|
|
|
|
document
|
|
|
|
.querySelector(
|
|
|
|
'[atto_tag="user.unfollow"]',
|
|
|
|
)
|
|
|
|
.classList.add("hidden");
|
|
|
|
document
|
|
|
|
.querySelector(
|
|
|
|
'[atto_tag="user.follow"]',
|
|
|
|
)
|
|
|
|
.classList.remove("hidden");
|
|
|
|
}
|
2025-03-31 20:02:09 -04:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
globalThis.toggle_block_user = async () => {
|
|
|
|
if (
|
|
|
|
!(await trigger("atto::confirm", [
|
|
|
|
"Are you sure you would like to do this?",
|
|
|
|
]))
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fetch(
|
2025-04-04 21:42:08 -04:00
|
|
|
"/api/v1/auth/user/{{ profile.id }}/block",
|
2025-03-31 20:02:09 -04:00
|
|
|
{
|
|
|
|
method: "POST",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.then((res) => res.json())
|
|
|
|
.then((res) => {
|
|
|
|
trigger("atto::toast", [
|
|
|
|
res.ok ? "success" : "error",
|
|
|
|
res.message,
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-04-01 15:03:56 -04:00
|
|
|
{% endif %} {% if not profile.settings.private_communities or
|
2025-04-01 16:12:13 -04:00
|
|
|
is_self or is_helper %}
|
2025-03-25 23:58:27 -04:00
|
|
|
<div class="card-nest">
|
2025-03-26 21:46:21 -04:00
|
|
|
<div class="card small flex gap-2 items-center">
|
2025-03-25 23:58:27 -04:00
|
|
|
{{ icon "users-round" }}
|
2025-03-29 00:26:56 -04:00
|
|
|
<span>{{ text "auth:label.joined_communities" }}</span>
|
2025-03-25 23:58:27 -04:00
|
|
|
</div>
|
|
|
|
|
2025-03-29 00:26:56 -04:00
|
|
|
<div class="card flex flex-wrap gap-2">
|
|
|
|
{% for community in communities %}
|
|
|
|
<a href="/community/{{ community.title }}">
|
|
|
|
{{ components::community_avatar(id=community.id,
|
|
|
|
community=community, size="48px") }}
|
|
|
|
</a>
|
|
|
|
{% endfor %}
|
|
|
|
</div>
|
2025-03-25 23:58:27 -04:00
|
|
|
</div>
|
2025-04-01 15:03:56 -04:00
|
|
|
{% endif %}
|
2025-03-25 23:58:27 -04:00
|
|
|
</div>
|
|
|
|
|
2025-04-01 16:12:13 -04:00
|
|
|
<div class="rhs w-full flex flex-col gap-4">
|
2025-04-06 13:43:12 -04:00
|
|
|
{% block content %}{% endblock %}
|
2025-04-01 16:12:13 -04:00
|
|
|
</div>
|
2025-03-25 23:58:27 -04:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article>
|
2025-04-11 18:13:41 -04:00
|
|
|
{% if not is_self and profile.settings.warning %}
|
2025-04-11 18:08:51 -04:00
|
|
|
<script>
|
|
|
|
setTimeout(() => {
|
|
|
|
// check for warning
|
|
|
|
trigger("warnings::open", [
|
|
|
|
"{{ profile.id }}",
|
|
|
|
"{{ warning_hash }}",
|
|
|
|
"?warning=true",
|
|
|
|
]);
|
|
|
|
}, 150);
|
|
|
|
</script>
|
|
|
|
{% endif %} {% if not use_user_theme %} {{ components::theme(user=profile,
|
|
|
|
theme_preference=profile.settings.profile_theme) }} {% endif %} {% endblock %}
|