Implement replies profile tab and boosts option

This commit is contained in:
Andrew Godwin 2023-05-13 11:07:57 -06:00
parent 31c4f89124
commit f5a3971ef8
10 changed files with 37 additions and 11 deletions

View file

@ -81,7 +81,12 @@ class TimelineService:
.order_by("-created") .order_by("-created")
) )
def identity_public(self, identity: Identity, include_boosts: bool = True): def identity_public(
self,
identity: Identity,
include_boosts: bool = True,
include_replies: bool = True,
):
""" """
Returns timeline events with all of an identity's publicly visible posts Returns timeline events with all of an identity's publicly visible posts
and their boosts and their boosts
@ -99,6 +104,8 @@ class TimelineService:
filter = filter | models.Q( filter = filter | models.Q(
type=TimelineEvent.Types.boost, subject_identity=identity type=TimelineEvent.Types.boost, subject_identity=identity
) )
if not include_replies:
filter = filter & models.Q(subject_post__in_reply_to__isnull=True)
return ( return (
self.event_queryset() self.event_queryset()
.filter( .filter(

View file

@ -430,6 +430,6 @@ class Preferences(Schema):
"posting:default:sensitive": False, "posting:default:sensitive": False,
"posting:default:language": None, "posting:default:language": None,
"reading:expand:media": "default", "reading:expand:media": "default",
"reading:expand:spoilers": identity.config_identity.expand_linked_cws, "reading:expand:spoilers": identity.config_identity.expand_content_warnings,
} }
) )

View file

@ -229,7 +229,6 @@ class Config(models.Model):
) )
class SystemOptions(pydantic.BaseModel): class SystemOptions(pydantic.BaseModel):
version: str = __version__ version: str = __version__
system_actor_public_key: str = "" system_actor_public_key: str = ""
@ -280,18 +279,15 @@ class Config(models.Model):
light_theme: bool = False light_theme: bool = False
class IdentityOptions(pydantic.BaseModel): class IdentityOptions(pydantic.BaseModel):
toot_mode: bool = False toot_mode: bool = False
default_post_visibility: int = 0 # Post.Visibilities.public default_post_visibility: int = 0 # Post.Visibilities.public
visible_follows: bool = True visible_follows: bool = True
search_enabled: bool = True search_enabled: bool = True
# Wellness Options
visible_reaction_counts: bool = True visible_reaction_counts: bool = True
expand_linked_cws: bool = True expand_content_warnings: bool = False
boosts_on_profile: bool = True
class DomainOptions(pydantic.BaseModel): class DomainOptions(pydantic.BaseModel):
site_name: str = "" site_name: str = ""
site_icon: UploadedImage | None = None site_icon: UploadedImage | None = None
hide_login: bool = False hide_login: bool = False

View file

@ -238,6 +238,7 @@ urlpatterns = [
), ),
# Identity views # Identity views
path("@<handle>/", identity.ViewIdentity.as_view()), path("@<handle>/", identity.ViewIdentity.as_view()),
path("@<handle>/replies/", identity.ViewIdentity.as_view(with_replies=True)),
path("@<handle>/inbox/", activitypub.Inbox.as_view()), path("@<handle>/inbox/", activitypub.Inbox.as_view()),
path("@<handle>/outbox/", activitypub.Outbox.as_view()), path("@<handle>/outbox/", activitypub.Outbox.as_view()),
path("@<handle>/collections/featured/", activitypub.FeaturedCollection.as_view()), path("@<handle>/collections/featured/", activitypub.FeaturedCollection.as_view()),

View file

@ -1,5 +1,6 @@
<section class="view-options"> <section class="view-options">
<a href="{{ identity.urls.view }}" {% if not section %}class="selected"{% endif %}><strong>{{ post_count }}</strong> Posts</a> <a href="{{ identity.urls.view }}" {% if not section %}class="selected"{% endif %}><strong>{{ post_count }}</strong> Posts</a>
<a href="{{ identity.urls.replies }}" {% if section == "replies" %}class="selected"{% endif %}>Posts & Replies</a>
{% if identity.local and identity.config_identity.visible_follows %} {% if identity.local and identity.config_identity.visible_follows %}
<a href="{{ identity.urls.following }}" {% if not inbound and section == "follows" %}class="selected"{% endif %}><strong>{{ following_count }}</strong> Following</a> <a href="{{ identity.urls.following }}" {% if not inbound and section == "follows" %}class="selected"{% endif %}><strong>{{ following_count }}</strong> Following</a>
<a href="{{ identity.urls.followers }}" {% if inbound and section == "follows" %}class="selected"{% endif %}><strong>{{ followers_count }}</strong> Follower{{ followers_count|pluralize }}</a> <a href="{{ identity.urls.followers }}" {% if inbound and section == "follows" %}class="selected"{% endif %}><strong>{{ followers_count }}</strong> Follower{{ followers_count|pluralize }}</a>

View file

@ -18,7 +18,7 @@
<legend>Appearance</legend> <legend>Appearance</legend>
{% include "forms/_field.html" with field=form.icon %} {% include "forms/_field.html" with field=form.icon %}
{% include "forms/_field.html" with field=form.image %} {% include "forms/_field.html" with field=form.image %}
{% include "forms/_field.html" with field=form.theme %} {% include "forms/_field.html" with field=form.boosts_on_profile %}
</fieldset> </fieldset>
<fieldset> <fieldset>

View file

@ -231,6 +231,7 @@ class Identity(StatorModel):
class urls(urlman.Urls): class urls(urlman.Urls):
view = "/@{self.username}@{self.domain_id}/" view = "/@{self.username}@{self.domain_id}/"
replies = "{view}replies/"
settings = "{view}settings/" settings = "{view}settings/"
action = "{view}action/" action = "{view}action/"
followers = "{view}followers/" followers = "{view}followers/"

View file

@ -32,6 +32,7 @@ class ViewIdentity(ListView):
template_name = "identity/view.html" template_name = "identity/view.html"
paginate_by = 25 paginate_by = 25
with_replies = False
def get(self, request, handle): def get(self, request, handle):
# Make sure we understand this handle # Make sure we understand this handle
@ -64,7 +65,11 @@ class ViewIdentity(ListView):
) )
def get_queryset(self): def get_queryset(self):
return TimelineService(None).identity_public(self.identity) return TimelineService(None).identity_public(
self.identity,
include_boosts=self.identity.config_identity.boosts_on_profile,
include_replies=self.with_replies,
)
def get_context_data(self): def get_context_data(self):
context = super().get_context_data() context = super().get_context_data()
@ -72,6 +77,8 @@ class ViewIdentity(ListView):
context["public_styling"] = True context["public_styling"] = True
context["post_count"] = self.identity.posts.count() context["post_count"] = self.identity.posts.count()
context["pinned_posts"] = TimelineService(self.identity).identity_pinned() context["pinned_posts"] = TimelineService(self.identity).identity_pinned()
if self.with_replies:
context["section"] = "replies"
if self.identity.config_identity.visible_follows: if self.identity.config_identity.visible_follows:
context["followers_count"] = self.identity.inbound_follows.filter( context["followers_count"] = self.identity.inbound_follows.filter(
state__in=FollowStates.group_active() state__in=FollowStates.group_active()

View file

@ -11,8 +11,12 @@ class PostingPage(SettingsPage):
"help_text": "Visibility to use as default for new posts.", "help_text": "Visibility to use as default for new posts.",
"choices": Post.Visibilities.choices, "choices": Post.Visibilities.choices,
}, },
"expand_content_warnings": {
"title": "Expand content warnings",
"help_text": "If content warnings should be expanded by default (not honoured by all clients)",
},
} }
layout = { layout = {
"Posting": ["default_post_visibility"], "Posting": ["default_post_visibility", "expand_content_warnings"],
} }

View file

@ -53,6 +53,11 @@ class ProfilePage(FormView):
widget=forms.Select(choices=[(True, "Enabled"), (False, "Disabled")]), widget=forms.Select(choices=[(True, "Enabled"), (False, "Disabled")]),
required=False, required=False,
) )
boosts_on_profile = forms.BooleanField(
help_text="Include your boosts with your posts on your profile page",
widget=forms.Select(choices=[(True, "Enabled"), (False, "Disabled")]),
required=False,
)
metadata = forms.JSONField( metadata = forms.JSONField(
label="Profile Metadata Fields", label="Profile Metadata Fields",
help_text="These values will appear on your profile below your bio", help_text="These values will appear on your profile below your bio",
@ -91,6 +96,7 @@ class ProfilePage(FormView):
"visible_follows": self.identity.config_identity.visible_follows, "visible_follows": self.identity.config_identity.visible_follows,
"metadata": self.identity.metadata or [], "metadata": self.identity.metadata or [],
"search_enabled": self.identity.config_identity.search_enabled, "search_enabled": self.identity.config_identity.search_enabled,
"boosts_on_profile": self.identity.config_identity.boosts_on_profile,
} }
def form_valid(self, form): def form_valid(self, form):
@ -125,6 +131,9 @@ class ProfilePage(FormView):
Config.set_identity( Config.set_identity(
self.identity, "search_enabled", form.cleaned_data["search_enabled"] self.identity, "search_enabled", form.cleaned_data["search_enabled"]
) )
Config.set_identity(
self.identity, "boosts_on_profile", form.cleaned_data["boosts_on_profile"]
)
messages.success(self.request, "Your profile has been updated.") messages.success(self.request, "Your profile has been updated.")
return redirect(".") return redirect(".")