user page redesign: misc tweaks

* separate source protocol from user in user labels
* make bridged protocol labels generic
* other visual tweaks

for #442
pull/671/head
Ryan Barrett 2023-10-10 21:19:26 -07:00
rodzic cc62d4cdb1
commit f37baeba58
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
8 zmienionych plików z 66 dodań i 52 usunięć

Wyświetl plik

@ -472,10 +472,7 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
return f"""\ return f"""\
<a class="h-card u-author" href="{self.web_url()}"> <a class="h-card u-author" href="{self.web_url()}">
<img src="{img}" class="profile"> <img src="{img}" class="profile">
<span class="logo" title="{self.__class__.__name__}">{self.LOGO_HTML}</span> {self.name()}</a>"""
{self.name()}
</a>
"""
class Object(StringIdModel): class Object(StringIdModel):

Wyświetl plik

@ -30,6 +30,16 @@ with app.test_request_context('/'):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
TEMPLATE_VARS = {
'as2': as2,
'g': g,
'isinstance': isinstance,
'logs': logs,
'PROTOCOLS': PROTOCOLS,
'set': set,
'util': util,
}
def load_user(protocol, id): def load_user(protocol, id):
"""Loads the current request's user into `g.user`. """Loads the current request's user into `g.user`.
@ -101,13 +111,10 @@ def web_user_redirects(**kwargs):
def profile(protocol, id): def profile(protocol, id):
load_user(protocol, id) load_user(protocol, id)
query = Object.query(OR(Object.users == g.user.key, query = Object.query(Object.users == g.user.key)
Object.notify == g.user.key))
objects, before, after = fetch_objects(query, by=Object.updated) objects, before, after = fetch_objects(query, by=Object.updated)
num_followers, num_following = count_followers() num_followers, num_following = count_followers()
return render_template('profile.html', **TEMPLATE_VARS, **locals())
return render_template('profile.html', logs=logs, util=util, g=g, **locals())
@app.get(f'/<any({",".join(PROTOCOLS)}):protocol>/<id>/home') @app.get(f'/<any({",".join(PROTOCOLS)}):protocol>/<id>/home')
@ -116,8 +123,7 @@ def home(protocol, id):
query = Object.query(Object.feed == g.user.key) query = Object.query(Object.feed == g.user.key)
objects, before, after = fetch_objects(query, by=Object.created) objects, before, after = fetch_objects(query, by=Object.created)
return render_template('home.html', **TEMPLATE_VARS, **locals())
return render_template('home.html', logs=logs, util=util, g=g, **locals())
@app.get(f'/<any({",".join(PROTOCOLS)}):protocol>/<id>/notifications') @app.get(f'/<any({",".join(PROTOCOLS)}):protocol>/<id>/notifications')
@ -126,8 +132,7 @@ def notifications(protocol, id):
query = Object.query(Object.notify == g.user.key) query = Object.query(Object.notify == g.user.key)
objects, before, after = fetch_objects(query, by=Object.updated) objects, before, after = fetch_objects(query, by=Object.updated)
return render_template('notifications.html', **TEMPLATE_VARS, **locals())
return render_template('notifications.html', logs=logs, util=util, g=g, **locals())
@app.get(f'/<any({",".join(PROTOCOLS)}):protocol>/<id>/<any(followers,following):collection>') @app.get(f'/<any({",".join(PROTOCOLS)}):protocol>/<id>/<any(followers,following):collection>')
@ -139,10 +144,8 @@ def followers_or_following(protocol, id, collection):
return render_template( return render_template(
f'{collection}.html', f'{collection}.html',
address=request.args.get('address'), address=request.args.get('address'),
as2=as2,
follow_url=request.values.get('url'), follow_url=request.values.get('url'),
g=g, **TEMPLATE_VARS,
util=util,
**locals(), **locals(),
) )
@ -202,7 +205,7 @@ def feed(protocol, id):
# syntax. maybe a fediverse kwarg down through the call chain? # syntax. maybe a fediverse kwarg down through the call chain?
if format == 'html': if format == 'html':
entries = [microformats2.object_to_html(a) for a in activities] entries = [microformats2.object_to_html(a) for a in activities]
return render_template('feed.html', util=util, g=g, **locals()) return render_template('feed.html', **TEMPLATE_VARS, **locals())
elif format == 'atom': elif format == 'atom':
body = atom.activities_to_atom(activities, actor=actor, title=title, body = atom.activities_to_atom(activities, actor=actor, title=title,
request_url=request.url) request_url=request.url)

Wyświetl plik

@ -304,7 +304,7 @@ button[disabled]:hover {
border-radius: 1em; border-radius: 1em;
} }
.btn-home img, .logo { .btn-home img, .logo, .logo img {
height: 1.1em; height: 1.1em;
margin-top: -.2em; margin-top: -.2em;
} }
@ -328,7 +328,7 @@ button[disabled]:hover {
} }
.tabs a { .tabs a {
border-bottom: 1px solid; border-bottom: 1px solid lightgray;
background: linear-gradient(white, #e8e8e8); background: linear-gradient(white, #e8e8e8);
padding-left: .5em; padding-left: .5em;
padding-right: .5em; padding-right: .5em;
@ -340,14 +340,23 @@ button[disabled]:hover {
text-decoration: none; text-decoration: none;
} }
.tabs a.active-tab { a.active-tab {
border-bottom: none; border-bottom: none;
border-left: 1px solid; border-left: 1px solid lightgray;
border-right: 1px solid;
background: inherit; background: inherit;
color: inherit; color: inherit;
} }
/* TODO: drop border-left above and switch to this once Firefix supports :has()
* https://caniuse.com/css-has
a:has(+ a.active-tab) {
border-right: 1px solid lightgray;
} */
a.active-tab + a {
border-left: 1px solid lightgray;
}
.disable-button, #bad-button { .disable-button, #bad-button {
border-color: red; border-color: red;
color: red; color: red;

Wyświetl plik

@ -25,7 +25,7 @@
{% endif %} {% endif %}
</li> </li>
{% else %} {% else %}
None yet. Check back soon! <span class="big">None yet. Check back soon!</span>
{% endfor %} {% endfor %}
</ul> </ul>

Wyświetl plik

@ -56,7 +56,7 @@
</div> </div>
</li> </li>
{% else %} {% else %}
<li class="row">Nothing yet!</li> <span class="big">None yet. Check back soon!</span>
{% endfor %} {% endfor %}
</ul> </ul>

Wyświetl plik

@ -36,27 +36,38 @@
{% endif %} {% endif %}
<div class="row"> <div class="row">
<span class="big">{{ g.user.user_link()|safe }}</span> <span class="big">
&middot; {{ g.user.user_link()|safe }}
{% if g.user.LABEL != 'activitypub' %} &middot;
bridged to <nobr>
<nobr title="Fediverse address"> <a href="{{ g.user.web_url() }}" title="{{ g.user.__class__.__name__ }}">
<img class="logo" src="/static/fediverse_logo.svg"> <span class="logo">{{ g.user.LOGO_HTML }}</span>
{{ g.user.ap_address() }} {{ g.user.handle_or_id() }}</a>
</nobr>
<form method="post" action="/webmention-interactive"> <!-- TODO: make this work with protocols other than Web -->
<input name="source" type="hidden" value="{{ g.user.web_url() }}" /> <form method="post" action="/webmention-interactive">
&nbsp; <input name="source" type="hidden" value="{{ g.user.web_url() }}" />
<button id="update-profile-button" type="submit" <button id="update-profile-button" type="submit" title="Update profile"
title="Update profile from web site" class="btn btn-default glyphicon glyphicon-refresh"></button>
class="btn btn-default glyphicon glyphicon-refresh"></button> </form>
</form> </nobr>
{% endif %} &middot;
</span>
{% for proto in set(PROTOCOLS.values()) %}
{% if proto and not isinstance(g.user, proto)
and proto.LABEL not in ('atproto', 'ui') %}
<nobr title="{{ proto.__name__ }} (bridged)">
<span class="logo">{{ proto.LOGO_HTML|safe }}</span>
{{ g.user.ap_address() }}
</nobr>
{% endif %}
{% endfor %}
</div> </div>
<!-- tabs --> <!-- tabs -->
<div class="row tabs"> <div class="row tabs">
<a></a> <a class="left-tab"></a>
<a href="{{ g.user.user_page_path() }}" <a href="{{ g.user.user_page_path() }}"
{% if tab == 'profile' %}class="active-tab"{% endif %} {% if tab == 'profile' %}class="active-tab"{% endif %}
>👤 Profile</a><a >👤 Profile</a><a
@ -66,7 +77,7 @@
href="{{ g.user.user_page_path('notifications') }}" href="{{ g.user.user_page_path('notifications') }}"
{% if tab == 'notifications' %}class="active-tab"{% endif %} {% if tab == 'notifications' %}class="active-tab"{% endif %}
>🔔 Notifications</a> >🔔 Notifications</a>
<a></a> <a class="right-tab"></a>
</div> </div>
{% block subtabs %} {% block subtabs %}

Wyświetl plik

@ -34,9 +34,7 @@ class CommonTest(TestCase):
self.assert_multiline_equals("""\ self.assert_multiline_equals("""\
<a class="h-card u-author" href="https://user.com/"> <a class="h-card u-author" href="https://user.com/">
<img src="" class="profile"> <img src="" class="profile">
<span class="logo" title="Web">🕸</span> user.com</a>""", common.pretty_link('https://user.com/'))
user.com
</a>""", common.pretty_link('https://user.com/'))
def test_redirect_wrap_empty(self): def test_redirect_wrap_empty(self):
self.assertIsNone(common.redirect_wrap(None)) self.assertIsNone(common.redirect_wrap(None))

Wyświetl plik

@ -139,17 +139,13 @@ class UserTest(TestCase):
self.assert_multiline_equals("""\ self.assert_multiline_equals("""\
<a class="h-card u-author" href="https://y.z/"> <a class="h-card u-author" href="https://y.z/">
<img src="" class="profile"> <img src="" class="profile">
<span class="logo" title="Web">🕸</span> y.z</a>""", g.user.user_link())
y.z
</a>""", g.user.user_link())
g.user.obj = Object(id='a', as2=ACTOR) g.user.obj = Object(id='a', as2=ACTOR)
self.assert_multiline_equals("""\ self.assert_multiline_equals("""\
<a class="h-card u-author" href="https://y.z/"> <a class="h-card u-author" href="https://y.z/">
<img src="https://user.com/me.jpg" class="profile"> <img src="https://user.com/me.jpg" class="profile">
<span class="logo" title="Web">🕸</span> Mrs. Foo</a>""", g.user.user_link())
Mrs. Foo
</a>""", g.user.user_link())
def test_is_web_url(self): def test_is_web_url(self):
for url in 'y.z', '//y.z', 'http://y.z', 'https://y.z': for url in 'y.z', '//y.z', 'http://y.z', 'https://y.z':