Phase 1 — spec compliance: - Add AS_PUBLIC constant; add to/cc fields to CreateActivity, DeleteActivity, UpdateActivity, AddActivity; populate on all broadcast call sites - Add @context to outbox CreateActivity items - Set manuallyApprovesFollowers: true to match actual Pending follow flow - Gate PermissiveVerifier behind FEDERATION_DEBUG env var - Add updated timestamp to Person actor JSON - Improve actor update delivery logging Phase 2a Batch 1 — AP layer: - Add /inbox shared inbox route; add endpoints.sharedInbox to Person - Paginate followers and following collections (20/page, OrderedCollectionPage) Phase 2a Batch 2 — profile completeness: - DB migrations: banner_path, also_known_as columns; user_profile_fields table - ProfileField value object; UserProfileFieldsRepository port - Banner image upload (stored via image-converter, surfaced as image in Person) - alsoKnownAs field in Person (account migration support) - Custom profile fields (up to 4 PropertyValue attachments in Person) - Profile settings UI: banner preview/upload, alsoKnownAs input, fields form - PUT /api/v1/profile/fields API endpoint
57 lines
1.7 KiB
HTML
57 lines
1.7 KiB
HTML
{% extends "base.html" %}
|
|
{% block content %}
|
|
<h1>Profile Settings</h1>
|
|
{% if saved %}
|
|
<p class="success">Saved.</p>
|
|
{% endif %}
|
|
<form method="post" action="/settings/profile" enctype="multipart/form-data">
|
|
<input type="hidden" name="_csrf" value="{{ ctx.csrf_token }}">
|
|
|
|
<label>
|
|
Bio<br>
|
|
<textarea name="bio">{% if let Some(b) = bio %}{{ b }}{% endif %}</textarea>
|
|
</label>
|
|
|
|
<label>
|
|
Also known as (actor URL for account migration)<br>
|
|
<input type="text" name="also_known_as" value="{% if let Some(v) = also_known_as %}{{ v }}{% endif %}">
|
|
</label>
|
|
|
|
{% if let Some(url) = avatar_url %}
|
|
<div>
|
|
<p>Current avatar:</p>
|
|
<img src="{{ url }}" alt="Current avatar" style="max-width:128px;max-height:128px;">
|
|
</div>
|
|
{% endif %}
|
|
<label>
|
|
Avatar image<br>
|
|
<input type="file" name="avatar" accept="image/jpeg,image/png,image/webp">
|
|
</label>
|
|
|
|
{% if let Some(url) = banner_url %}
|
|
<div>
|
|
<p>Current banner:</p>
|
|
<img src="{{ url }}" alt="Current banner" style="max-width:600px;max-height:200px;">
|
|
</div>
|
|
{% endif %}
|
|
<label>
|
|
Banner image<br>
|
|
<input type="file" name="banner" accept="image/jpeg,image/png,image/webp">
|
|
</label>
|
|
|
|
<fieldset>
|
|
<legend>Profile fields (max 4)</legend>
|
|
{% for i in 0..4usize %}
|
|
<div>
|
|
<input type="text" name="field_name_{{ i }}" placeholder="Label"
|
|
value="{% if let Some((n, _)) = profile_fields.get(*i) %}{{ n }}{% endif %}">
|
|
<input type="text" name="field_value_{{ i }}" placeholder="Value"
|
|
value="{% if let Some((_, v)) = profile_fields.get(*i) %}{{ v }}{% endif %}">
|
|
</div>
|
|
{% endfor %}
|
|
</fieldset>
|
|
|
|
<button type="submit">Save</button>
|
|
</form>
|
|
{% endblock %}
|