381 lines
19 KiB
Common Lisp
381 lines
19 KiB
Common Lisp
(text "{% extends \"root.html\" %} {% block head %}")
|
|
(title
|
|
(text "{{ profile.username }} - {{ config.name }}"))
|
|
|
|
(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 }}!"))
|
|
|
|
(text "{% endblock %} {% block body %} {{ macros::nav() }}")
|
|
(article
|
|
(div
|
|
("class" "content_container flex flex-col gap-4")
|
|
(text "{{ components::banner(username=profile.username) }}")
|
|
(div
|
|
("class" "w-full flex gap-4 flex-collapse")
|
|
(div
|
|
("class" "lhs flex flex-col gap-2 sm:w-full")
|
|
("style" "width: 22rem; min-width: 22rem")
|
|
(div
|
|
("class" "card-nest w-full")
|
|
(div
|
|
("class" "card flex gap-2")
|
|
("id" "user_avatar_and_name")
|
|
(text "{{ components::avatar(username=profile.username,size=\"72px\") }}")
|
|
(div
|
|
("class" "flex flex-col")
|
|
(h3
|
|
("id" "username")
|
|
("class" "username flex items-center gap-2 flex-wrap w-full")
|
|
(span
|
|
("class" "name shorter")
|
|
(text "{{ components::username(user=profile) }}"))
|
|
(text "{% if profile.is_verified -%}")
|
|
(span
|
|
("title" "Verified")
|
|
("style" "color: var(--color-primary);")
|
|
("class" "flex items-center")
|
|
(text "{{ icon \"badge-check\" }}"))
|
|
(text "{%- endif %} {% if profile.permissions|has_supporter -%}")
|
|
(span
|
|
("title" "Supporter")
|
|
("style" "color: var(--color-primary);")
|
|
("class" "flex items-center")
|
|
(text "{{ icon \"star\" }}"))
|
|
(text "{%- endif %} {% if profile.permissions|has_staff_badge -%}")
|
|
(span
|
|
("title" "Staff")
|
|
("style" "color: var(--color-primary);")
|
|
("class" "flex items-center")
|
|
(text "{{ icon \"shield-user\" }}"))
|
|
(text "{%- endif %} {% if profile.permissions|has_banned -%}")
|
|
(span
|
|
("title" "Banned")
|
|
("style" "color: var(--color-primary);")
|
|
("class" "flex items-center")
|
|
(text "{{ icon \"shield-ban\" }}"))
|
|
(text "{%- endif %}"))
|
|
(span
|
|
("class" "fade")
|
|
(text "{{ profile.username }}"))))
|
|
(div
|
|
("class" "card flex flex-col items-center gap-2")
|
|
("id" "social")
|
|
(text "{% if profile.settings.status -%}")
|
|
(p
|
|
(text "{{ profile.settings.status }}"))
|
|
(text "{%- endif %}")
|
|
(div
|
|
("class" "w-full flex")
|
|
(a
|
|
("href" "/@{{ profile.username }}/followers")
|
|
("class" "w-full flex justify-center items-center gap-2")
|
|
(h4
|
|
(text "{{ profile.follower_count }}"))
|
|
(span
|
|
(text "{{ text \"auth:label.followers\" }}")))
|
|
(a
|
|
("href" "/@{{ profile.username }}/following")
|
|
("class" "w-full flex justify-center items-center gap-2")
|
|
(h4
|
|
(text "{{ profile.following_count }}"))
|
|
(span
|
|
(text "{{ text \"auth:label.following\" }}"))))
|
|
(text "{% if is_following_you -%}")
|
|
(b
|
|
("class" "notification chip w-content flex items-center gap-2")
|
|
(text "{{ icon \"heart\" }}")
|
|
(span
|
|
(text "Follows you")))
|
|
(text "{%- endif %}")))
|
|
(div
|
|
("class" "card-nest flex flex-col")
|
|
(div
|
|
("id" "bio")
|
|
("class" "card small no_p_margin")
|
|
(text "{{ profile.settings.biography|markdown|safe }}"))
|
|
(div
|
|
("class" "card flex flex-col gap-2")
|
|
(div
|
|
("style" "display: contents;")
|
|
(text "{% if profile.connections.Spotify and profile.connections.Spotify[0].data.name -%} {{ components::spotify_playing(state=profile.connections.Spotify[1]) }} {% elif profile.connections.LastFm and profile.connections.LastFm[0].data.name %} {{ components::last_fm_playing(state=profile.connections.LastFm[1]) }} {%- endif %}"))
|
|
(div
|
|
("class" "w-full flex justify-between items-center")
|
|
(span
|
|
("class" "notification chip")
|
|
(text "ID"))
|
|
(button
|
|
("title" "Copy")
|
|
("onclick" "trigger('atto::copy_text', ['{{ profile.id }}'])")
|
|
("class" "camo small")
|
|
(text "{{ icon \"copy\" }}")))
|
|
(div
|
|
("class" "w-full flex justify-between items-center")
|
|
(span
|
|
("class" "notification chip")
|
|
(text "Joined"))
|
|
(span
|
|
("class" "date")
|
|
(text "{{ profile.created }}")))
|
|
(div
|
|
("class" "w-full flex justify-between items-center")
|
|
(span
|
|
("class" "notification chip")
|
|
(text "Posts"))
|
|
(span
|
|
(text "{{ profile.post_count }}")))
|
|
(text "{% 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")
|
|
(text "Last seen"))
|
|
(div
|
|
("class" "flex")
|
|
(text "{{ components::online_indicator(user=profile) }}")
|
|
(span
|
|
("class" "date")
|
|
(text "{{ profile.last_seen }}"))))
|
|
(text "{%- endif %}")
|
|
|
|
(text "{% if user and user.id != profile.id -%}")
|
|
(hr)
|
|
(div
|
|
("class" "flex flex-wrap gap-2 w-full fade")
|
|
(a
|
|
("class" "red")
|
|
("href" "javascript:trigger('me::report', ['{{ profile.id }}', 'user'])")
|
|
(text "({{ lang[\"general:action.report\"]|lower }})")))
|
|
(text "{%- endif %}")))
|
|
(text "{% if not is_self and user -%}")
|
|
(div
|
|
("class" "card-nest")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "{{ text \"auth:label.relationship\" }}")))
|
|
(div
|
|
("class" "card flex gap-2 flex-wrap")
|
|
(text "{% if not is_blocking -%}")
|
|
(button
|
|
("onclick" "toggle_follow_user(event)")
|
|
("class" "{% if is_following %} hidden{% endif %}")
|
|
("atto_tag" "user.follow")
|
|
(text "{{ icon \"user-plus\" }}")
|
|
(span
|
|
(text "{{ text \"auth:action.follow\" }}")))
|
|
(button
|
|
("onclick" "toggle_follow_user(event)")
|
|
("class" "quaternary red{% if not is_following %} hidden{% endif %}")
|
|
("atto_tag" "user.unfollow")
|
|
(text "{{ icon \"user-minus\" }}")
|
|
(span
|
|
(text "{{ text \"auth:action.unfollow\" }}")))
|
|
(button
|
|
("onclick" "toggle_block_user()")
|
|
("class" "quaternary red")
|
|
(text "{{ icon \"shield\" }}")
|
|
(span
|
|
(text "{{ text \"auth:action.block\" }}")))
|
|
(text "{% else %}")
|
|
(button
|
|
("onclick" "toggle_block_user()")
|
|
("class" "quaternary red")
|
|
(text "{{ icon \"shield-off\" }}")
|
|
(span
|
|
(text "{{ text \"auth:action.unblock\" }}")))
|
|
(text "{%- endif %} {% if not user.settings.private_chats or is_following_you %}")
|
|
(button
|
|
("onclick" "create_group_chat()")
|
|
("class" "quaternary")
|
|
(text "{{ icon \"message-circle\" }}")
|
|
(span
|
|
(text "{{ text \"auth:action.message\" }}")))
|
|
(text "{%- endif %} {% if is_helper -%}")
|
|
(a
|
|
("href" "/mod_panel/profile/{{ profile.id }}")
|
|
("class" "button quaternary")
|
|
(text "{{ icon \"shield\" }}")
|
|
(span
|
|
(text "{{ text \"general:action.manage\" }}")))
|
|
(text "{%- endif %}")
|
|
(script
|
|
(text "globalThis.create_group_chat = async () => {
|
|
fetch(\"/api/v1/channels/group\", {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
title: \"{{ user.username }} & {{ profile.username }}\",
|
|
members: [\"{{ profile.id }}\"],
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
|
|
if (res.ok) {
|
|
window.location.href = `/chats/0/${res.payload}`;
|
|
}
|
|
});
|
|
};
|
|
|
|
globalThis.toggle_follow_user = async (e) => {
|
|
await trigger(\"atto::debounce\", [
|
|
\"users::follow\",
|
|
]);
|
|
|
|
fetch(
|
|
\"/api/v1/auth/user/{{ profile.id }}/follow\",
|
|
{
|
|
method: \"POST\",
|
|
},
|
|
)
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
|
|
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\");
|
|
}
|
|
});
|
|
};
|
|
|
|
globalThis.toggle_block_user = async () => {
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this?\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(
|
|
\"/api/v1/auth/user/{{ profile.id }}/block\",
|
|
{
|
|
method: \"POST\",
|
|
},
|
|
)
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};"))))
|
|
(text "{%- endif %} {% if not profile.settings.private_communities or is_self or is_helper %}")
|
|
(div
|
|
("class" "card-nest")
|
|
(div
|
|
("class" "card small flex gap-2 items-center")
|
|
(text "{{ icon \"users-round\" }}")
|
|
(span
|
|
(text "{{ text \"auth:label.joined_communities\" }}")))
|
|
(div
|
|
("class" "card flex flex-wrap gap-2")
|
|
(text "{% for community in communities %}")
|
|
(a
|
|
("href" "/community/{{ community.title }}")
|
|
(text "{{ components::community_avatar(id=community.id, community=community, size=\"48px\") }}"))
|
|
(text "{% endfor %}")))
|
|
(text "{%- endif %}")
|
|
(div
|
|
("class" "flex flex-col gap-2")
|
|
("id" "connections")
|
|
(text "{% for key, value in profile.connections %} {% if value[0].data.name and value[0].show_on_profile %}")
|
|
(a
|
|
("class" "card small flush flex items-center justify-between gap-2")
|
|
("href" "{{ components::connection_url(key=key, value=value) }}")
|
|
(div
|
|
("class" "flex items-center gap-2")
|
|
(text "{{ components::connection_icon(key=key) }}")
|
|
(b
|
|
(text "{{ value[0].data.name }}")))
|
|
(button
|
|
("class" "camo small")
|
|
(text "{{ icon \"external-link\" }}")))
|
|
(text "{%- endif %} {% endfor %}")))
|
|
(div
|
|
("class" "rhs w-full flex flex-col gap-4")
|
|
(text "{% block content %}{% endblock %}")))))
|
|
|
|
(text "{% if not is_self and profile.settings.warning -%}")
|
|
(script
|
|
(text "setTimeout(() => {
|
|
// check for warning
|
|
trigger(\"warnings::open\", [
|
|
\"{{ profile.id }}\",
|
|
\"{{ warning_hash }}\",
|
|
\"?warning=true\",
|
|
]);
|
|
}, 150);"))
|
|
|
|
(text "{%- endif %} {% if not use_user_theme -%} {{ components::theme(user=profile, theme_preference=profile.settings.profile_theme) }} {%- endif %} {% endblock %}")
|