mirror of
https://github.com/jointakahe/takahe.git
synced 2024-11-21 23:01:00 +00:00
Fallback avatars in about 500 bytes. (#269)
Also create a new re-usable identity banner template. Fix super long handles (closes #270)
This commit is contained in:
parent
d32a686eb1
commit
dab8dd59a7
9 changed files with 159 additions and 93 deletions
|
@ -438,7 +438,7 @@ p.authorization-code {
|
|||
|
||||
.icon-menu .option {
|
||||
display: block;
|
||||
margin: 0px 0 20px 0;
|
||||
margin: 0 0 20px 0;
|
||||
background: var(--color-bg-box);
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.1);
|
||||
color: inherit;
|
||||
|
@ -457,6 +457,10 @@ p.authorization-code {
|
|||
color: var(--color-text-dull);
|
||||
}
|
||||
|
||||
.icon-menu .option-actions {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.icon-menu .option.empty:hover,
|
||||
.icon-menu .option.static:hover {
|
||||
border: 2px solid rgba(255, 255, 255, 0);
|
||||
|
@ -482,8 +486,20 @@ p.authorization-code {
|
|||
font-size: 200%;
|
||||
}
|
||||
|
||||
.icon-menu .option .handle {
|
||||
margin-right: 20px;
|
||||
.icon-menu .option.hashtags {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.icon-menu .option.hashtags .tag {
|
||||
min-width: 0;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.icon-menu .option.hashtags .count {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.icon-menu .option .pill {
|
||||
|
@ -500,16 +516,10 @@ p.authorization-code {
|
|||
}
|
||||
|
||||
.icon-menu .option time {
|
||||
float: right;
|
||||
color: var(--color-text-duller);
|
||||
margin: 14px 0 0 0;
|
||||
}
|
||||
|
||||
.icon-menu .option .right {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.icon-menu .option button {
|
||||
margin-top: 8px;
|
||||
margin-right: 20px;
|
||||
|
@ -1015,6 +1025,34 @@ table.metadata td .emoji {
|
|||
min-width: 16px;
|
||||
}
|
||||
|
||||
/* Identity banner */
|
||||
|
||||
.identity-banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.identity-banner .handle {
|
||||
display: block;
|
||||
padding: 0 10px;
|
||||
vertical-align: middle;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.identity-banner .handle .link,
|
||||
.identity-banner .handle .small {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.identity-banner .avatar-link {
|
||||
line-height: 0; /* Fixes a bit of extra padding on the bottom of the link. */
|
||||
}
|
||||
|
||||
/* Posts */
|
||||
|
||||
.post {
|
||||
|
@ -1043,31 +1081,24 @@ form .post {
|
|||
.post .icon {
|
||||
height: 48px;
|
||||
width: auto;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.post.mini .icon {
|
||||
height: 28px;
|
||||
width: auto;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.post .emoji {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.post .handle {
|
||||
display: block;
|
||||
padding: 7px 0 0 64px;
|
||||
}
|
||||
|
||||
.post.mini .handle {
|
||||
padding: 7px 0 0 36px;
|
||||
.post .post-banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.post time {
|
||||
display: block;
|
||||
float: right;
|
||||
color: var(--color-text-duller);
|
||||
width: 65px;
|
||||
text-align: center;
|
||||
|
|
8
static/js/minidenticons.min.js
vendored
Normal file
8
static/js/minidenticons.min.js
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
function identicon(t,e=50,i=50){const n=t.split("").reduce(((t,e)=>16777619*((t^e.charCodeAt(0))>>>0)),2166136261);const s=n/16777619%18*20;return[...Array(t?25:0)].reduce(((t,e,i)=>n%(16-i%15)<4?t+`<rect x="${i>14?7-~~(i/5):~~(i/5)}" y="${i%5}" width="1" height="1"/>`:t),`<svg viewBox="-1.5 -1.5 8 8" xmlns="http://www.w3.org/2000/svg" fill="hsl(${s} ${e}% ${i}%)">`)+"</svg>"}
|
||||
function generate_avatar(handle) {
|
||||
element.src = URL.createObjectURL(
|
||||
new Blob([identicon(handle)], {
|
||||
type: 'image/svg+xml;charset=utf8'
|
||||
}
|
||||
));
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
{% load activity_tags %}
|
||||
<div class="post user" data-takahe-id="{{ identity.id }}">
|
||||
|
||||
<a href="{{ identity.urls.view }}">
|
||||
<img src="{{ identity.local_icon_url.relative }}" class="icon" alt="Avatar for {{ identity.name_or_handle }}" loading="lazy">
|
||||
</a>
|
||||
{% include "identity/_identity_banner.html" with identity=identity %}
|
||||
|
||||
{% if created %}
|
||||
<time>
|
||||
|
|
|
@ -2,32 +2,29 @@
|
|||
{% load activity_tags %}
|
||||
<div class="post {% if reply %}reply{% endif %} {{ post.summary_class }}" data-takahe-id="{{ post.id }}" role="article" tabindex="0">
|
||||
|
||||
<a href="{{ post.author.urls.view }}" tabindex="-1">
|
||||
<img src="{{ post.author.local_icon_url.relative }}" class="icon" loading="lazy">
|
||||
</a>
|
||||
|
||||
<time _="on click go url {% if link_original %}{{ post.url }}{% else %}{{ post.urls.view }}{% endif %} then halt">
|
||||
{% if post.visibility == 0 %}
|
||||
<i class="visibility fa-solid fa-earth-oceania" title="Public" aria-label="public"></i>
|
||||
{% elif post.visibility == 1 %}
|
||||
<i class="visibility fa-solid fa-lock-open" title="Unlisted" aria-label="unlisted"></i>
|
||||
{% elif post.visibility == 2 %}
|
||||
<i class="visibility fa-solid fa-lock" title="Followers Only" aria-label="followers only"></i>
|
||||
{% elif post.visibility == 3 %}
|
||||
<i class="visibility fa-solid fa-at" title="Mentioned Only" aria-label="mentioned only"></i>
|
||||
{% elif post.visibility == 4 %}
|
||||
<i class="visibility fa-solid fa-link-slash" title="Local Only" aria-label="local only"></i>
|
||||
{% endif %}
|
||||
{% if post.published %}
|
||||
<a href="{% if link_original %}{{ post.url }}{% else %}{{ post.urls.view }}{% endif %}" title="{{ post.published }}">{{ post.published | timedeltashort }}</a>
|
||||
{% else %}
|
||||
<a href="{% if link_original %}{{ post.url }}{% else %}{{ post.urls.view }}{% endif %}" title="{{ post.created }}">{{ post.created | timedeltashort }}</a>
|
||||
{% endif %}
|
||||
</time>
|
||||
|
||||
<a href="{{ post.author.urls.view }}" class="handle">
|
||||
<span class="link">{{ post.author.html_name_or_handle }}</span> <small>@{{ post.author.handle }}</small>
|
||||
</a>
|
||||
<div class="post-banner">
|
||||
{% include "identity/_identity_banner.html" with identity=post.author %}
|
||||
<div>
|
||||
<time _="on click go url {% if link_original %}{{ post.url }}{% else %}{{ post.urls.view }}{% endif %} then halt">
|
||||
{% if post.visibility == 0 %}
|
||||
<i class="visibility fa-solid fa-earth-oceania" title="Public" aria-label="public"></i>
|
||||
{% elif post.visibility == 1 %}
|
||||
<i class="visibility fa-solid fa-lock-open" title="Unlisted" aria-label="unlisted"></i>
|
||||
{% elif post.visibility == 2 %}
|
||||
<i class="visibility fa-solid fa-lock" title="Followers Only" aria-label="followers only"></i>
|
||||
{% elif post.visibility == 3 %}
|
||||
<i class="visibility fa-solid fa-at" title="Mentioned Only" aria-label="mentioned only"></i>
|
||||
{% elif post.visibility == 4 %}
|
||||
<i class="visibility fa-solid fa-link-slash" title="Local Only" aria-label="local only"></i>
|
||||
{% endif %}
|
||||
{% if post.published %}
|
||||
<a href="{% if link_original %}{{ post.url }}{% else %}{{ post.urls.view }}{% endif %}" title="{{ post.published }}">{{ post.published | timedeltashort }}</a>
|
||||
{% else %}
|
||||
<a href="{% if link_original %}{{ post.url }}{% else %}{{ post.urls.view }}{% endif %}" title="{{ post.created }}">{{ post.created | timedeltashort }}</a>
|
||||
{% endif %}
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if post.summary %}
|
||||
{% if config_identity.expand_linked_cws %}
|
||||
|
|
|
@ -16,36 +16,32 @@
|
|||
|
||||
<section class="icon-menu">
|
||||
{% for identity in page_obj %}
|
||||
<a class="option" href="{{ identity.urls.view }}">
|
||||
<img src="{{ identity.local_icon_url.relative }}" loading="lazy">
|
||||
<span class="handle">
|
||||
{{ identity.html_name_or_handle }}
|
||||
<small>@{{ identity.handle }}</small>
|
||||
</span>
|
||||
|
||||
<a class="option " href="{{ identity.urls.view }}">
|
||||
<div class="option-content">
|
||||
{% include "identity/_identity_banner.html" with identity=identity link_avatar=False link_handle=False %}
|
||||
</div>
|
||||
<div class="option-actions">
|
||||
{% if identity.id in outbound_ids %}
|
||||
<span class="pill">Following</span>
|
||||
<span class="pill">Following</span>
|
||||
{% endif %}
|
||||
{% if identity.id in inbound_ids %}
|
||||
<span class="pill">Follows You</span>
|
||||
{% endif %}
|
||||
|
||||
<div class="right">
|
||||
{% if inbound %}
|
||||
<form action="{{ identity.urls.action }}" method="POST" class="follow">
|
||||
{% csrf_token %}
|
||||
{% if identity.id in outbound_ids %}
|
||||
<input type="hidden" name="action" value="unfollow">
|
||||
<button class="destructive">Unfollow</button>
|
||||
{% else %}
|
||||
<input type="hidden" name="action" value="follow">
|
||||
<button>Follow</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<time>{{ identity.follow_date | timedeltashort }} ago</time>
|
||||
</div>
|
||||
{% if inbound %}
|
||||
<form action="{{ identity.urls.action }}" method="POST" class="follow">
|
||||
{% csrf_token %}
|
||||
{% if identity.id in outbound_ids %}
|
||||
<input type="hidden" name="action" value="unfollow">
|
||||
<button class="destructive">Unfollow</button>
|
||||
{% else %}
|
||||
<input type="hidden" name="action" value="follow">
|
||||
<button>Follow</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endif %}
|
||||
<time>{{ identity.follow_date | timedeltashort }} ago</time>
|
||||
</div>
|
||||
</a>
|
||||
{% empty %}
|
||||
<p class="option empty">You have no follows.</p>
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
{% block content %}
|
||||
<section class="icon-menu">
|
||||
{% for hashtag in page_obj %}
|
||||
<a class="option" href="{{ hashtag.urls.admin_edit }}">
|
||||
<a class="option hashtags" href="{{ hashtag.urls.admin_edit }}">
|
||||
<div class="tag">
|
||||
<i class="fa-solid fa-hashtag"></i>
|
||||
<span class="handle">
|
||||
{{ hashtag.display_name }}
|
||||
|
@ -13,22 +14,25 @@
|
|||
{% if hashtag.public %}Public{% elif hashtag.public is None %}Unreviewed{% else %}Private{% endif %}
|
||||
</small>
|
||||
</span>
|
||||
{% if hashtag.stats %}
|
||||
<span class="handle">
|
||||
<small>Total:</small>
|
||||
{{ hashtag.stats.total }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if hashtag.aliases %}
|
||||
|
||||
<span class="handle">
|
||||
<small>Aliases:</small>
|
||||
</div>
|
||||
{% if hashtag.stats %}
|
||||
<div class="count">
|
||||
<span class="handle">
|
||||
{{ hashtag.stats.total }}
|
||||
<small>Total</small>
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if hashtag.aliases %}
|
||||
<div class="count">
|
||||
<span class="handle">
|
||||
{% for alias in hashtag.aliases %}
|
||||
{{ alias }}{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
<small>Aliases</small>
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
{% empty %}
|
||||
<p class="option empty">There are no hashtags yet.</p>
|
||||
|
|
|
@ -20,16 +20,14 @@
|
|||
<section class="icon-menu">
|
||||
{% for identity in page_obj %}
|
||||
<a class="option" href="{{ identity.urls.admin_edit }}">
|
||||
<img src="{{ identity.local_icon_url.relative }}" class="icon" alt="Avatar for {{ identity.name_or_handle }}" loading="lazy">
|
||||
<span class="handle">
|
||||
{{ identity.html_name_or_handle }}
|
||||
<small>
|
||||
{{ identity.handle }}
|
||||
</small>
|
||||
</span>
|
||||
<div class="option-content">
|
||||
{% include "identity/_identity_banner.html" with identity=identity link_avatar=False link_handle=False %}
|
||||
</div>
|
||||
<div class="option-actions">
|
||||
{% if identity.banned %}
|
||||
<span class="pill bad">Banned</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</a>
|
||||
{% empty %}
|
||||
<p class="option empty">
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="shortcut icon" href="{{ config.site_icon }}">
|
||||
<script src="{% static "js/hyperscript.min.js" %}"></script>
|
||||
<script src="{% static "js/htmx.min.js" %}"></script>
|
||||
<script src="{% static "js/minidenticons.min.js" %}"></script>
|
||||
<style>
|
||||
body {
|
||||
--color-highlight: {{ config.highlight_color }};
|
||||
|
|
33
templates/identity/_identity_banner.html
Normal file
33
templates/identity/_identity_banner.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
<div class="identity-banner">
|
||||
{% if link_avatar is False %}
|
||||
<div class="avatar-link">
|
||||
{% else %}
|
||||
<a href="{{ identity.urls.view }}" tabindex="-1" class="avatar-link">
|
||||
{% endif %}
|
||||
<img
|
||||
src="{{ identity.local_icon_url.relative }}"
|
||||
class="icon"
|
||||
alt="Avatar for {{ identity.name_or_handle }}"
|
||||
loading="lazy"
|
||||
data-handle="{{ identity.name_or_handle }}"
|
||||
_="on error set my.src to generate_avatar(@data-handle)"
|
||||
>
|
||||
{% if link_avatar is False%}
|
||||
</div>
|
||||
{% else %}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if link_handle is False%}
|
||||
<div class="handle">
|
||||
{% else %}
|
||||
<a href="{{ identity.urls.view }}" class="handle">
|
||||
{% endif %}
|
||||
<div class="link">{{ identity.html_name_or_handle }}</div>
|
||||
<small>@{{ identity.handle }}</small>
|
||||
{% if link_handle is False %}
|
||||
</div>
|
||||
{% else %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
Loading…
Reference in a new issue