diff --git a/.env.example b/.env.example
index d2b43e171..e8302af42 100644
--- a/.env.example
+++ b/.env.example
@@ -23,7 +23,8 @@ POSTGRES_USER=fedireads
POSTGRES_DB=fedireads
POSTGRES_HOST=db
-# Redis as activitystreams manager
+# Redis activity stream manager
+MAX_STREAM_LENGTH=200
REDIS_ACTIVITY_HOST=redis_activity
REDIS_ACTIVITY_PORT=6379
REDIS_ACTIVITY_PASSWORD=redispassword345
diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py
index 74f491022..768eb2084 100644
--- a/bookwyrm/activitypub/base_activity.py
+++ b/bookwyrm/activitypub/base_activity.py
@@ -248,7 +248,9 @@ def get_model_from_type(activity_type):
return model[0]
-def resolve_remote_id(remote_id, model=None, refresh=False, save=True):
+def resolve_remote_id(
+ remote_id, model=None, refresh=False, save=True, get_activity=False
+):
""" take a remote_id and return an instance, creating if necessary """
if model: # a bonus check we can do if we already know the model
result = model.find_existing_by_remote_id(remote_id)
@@ -272,5 +274,8 @@ def resolve_remote_id(remote_id, model=None, refresh=False, save=True):
return result if not get_activity else result.to_activity_dataclass()
item = model.activity_serializer(**data)
+ if get_activity:
+ return item
+
# if we're refreshing, "result" will be set and we'll update it
return item.to_model(model=model, instance=result, save=save)
diff --git a/bookwyrm/migrations/0058_auto_20210324_1536.py b/bookwyrm/migrations/0058_auto_20210324_1536.py
new file mode 100644
index 000000000..0fa8c90b6
--- /dev/null
+++ b/bookwyrm/migrations/0058_auto_20210324_1536.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.1.6 on 2021-03-24 15:36
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("bookwyrm", "0057_user_discoverable"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="status",
+ options={"ordering": ("-published_date",)},
+ ),
+ ]
diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py
index 1690ec37d..8038e3ee5 100644
--- a/bookwyrm/models/status.py
+++ b/bookwyrm/models/status.py
@@ -58,6 +58,11 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
serialize_reverse_fields = [("attachments", "attachment", "id")]
deserialize_reverse_fields = [("attachments", "attachment")]
+ class Meta:
+ """ default sorting """
+
+ ordering = ("-published_date",)
+
def save(self, *args, **kwargs):
""" save and notify """
super().save(*args, **kwargs)
@@ -118,12 +123,14 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
""" keep notes if they are replies to existing statuses """
if activity.type == "Announce":
try:
- boosted = activitypub.resolve_remote_id(activity.object, save=False)
+ boosted = activitypub.resolve_remote_id(
+ activity.object, get_activity=True
+ )
except activitypub.ActivitySerializerError:
# if we can't load the status, definitely ignore it
return True
# keep the boost if we would keep the status
- return cls.ignore_activity(boosted.to_activity_dataclass())
+ return cls.ignore_activity(boosted)
# keep if it if it's a custom type
if activity.type != "Note":
@@ -344,7 +351,7 @@ class Boost(ActivityMixin, Status):
def save(self, *args, **kwargs):
""" save and notify """
super().save(*args, **kwargs)
- if not self.boosted_status.user.local:
+ if not self.boosted_status.user.local or self.boosted_status.user == self.user:
return
notification_model = apps.get_model("bookwyrm.Notification", require_ready=True)
diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py
index 0f010da27..1aa7c3bea 100644
--- a/bookwyrm/settings.py
+++ b/bookwyrm/settings.py
@@ -97,7 +97,7 @@ REDIS_ACTIVITY_HOST = env("REDIS_ACTIVITY_HOST", "localhost")
REDIS_ACTIVITY_PORT = env("REDIS_ACTIVITY_PORT", 6379)
REDIS_ACTIVITY_PASSWORD = env("REDIS_ACTIVITY_PASSWORD")
-MAX_STREAM_LENGTH = env("MAX_STREAM_LENGTH", 200)
+MAX_STREAM_LENGTH = int(env("MAX_STREAM_LENGTH", 200))
STREAMS = ["home", "local", "federated"]
# Database
diff --git a/bookwyrm/static/css/format.css b/bookwyrm/static/css/format.css
index c68eb40d2..6a1167b26 100644
--- a/bookwyrm/static/css/format.css
+++ b/bookwyrm/static/css/format.css
@@ -34,6 +34,29 @@ html {
.hidden {
display: none !important;
}
+.hidden.transition-y, .hidden.transition-x {
+ display: block !important;
+ visibility: hidden !important;
+ height: 0;
+ width: 0;
+ margin: 0;
+ padding: 0;
+}
+.transition-y {
+ transition-property: height, margin-top, margin-bottom, padding-top, padding-bottom;
+ transition-duration: 0.5s;
+ transition-timing-function: ease;
+}
+.transition-x {
+ transition-property: width, margin-left, margin-right, padding-left, padding-right;
+ transition-duration: 0.5s;
+ transition-timing-function: ease;
+}
+@media (prefers-reduced-motion: reduce) {
+ .transition-x, .transition-y {
+ transition-duration: 0.001ms !important;
+ }
+}
/* --- STARS --- */
.rate-stars button.icon {
diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html
index 379bf9272..bc35d3b90 100644
--- a/bookwyrm/templates/feed/feed.html
+++ b/bookwyrm/templates/feed/feed.html
@@ -28,7 +28,7 @@
{# announcements and system messages #}
{% if not activities.number > 1 %}
-
+
{% blocktrans %}load 0 unread status(es){% endblocktrans %}
diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html
index d08b18202..4f6573582 100644
--- a/bookwyrm/templates/layout.html
+++ b/bookwyrm/templates/layout.html
@@ -139,7 +139,7 @@
{% trans "Notifications" %}
-
+
{{ request.user | notification_count }}
diff --git a/bookwyrm/tests/views/test_interaction.py b/bookwyrm/tests/views/test_interaction.py
index 40152c0fb..297eeb73d 100644
--- a/bookwyrm/tests/views/test_interaction.py
+++ b/bookwyrm/tests/views/test_interaction.py
@@ -95,6 +95,23 @@ class InteractionViews(TestCase):
self.assertEqual(notification.related_user, self.remote_user)
self.assertEqual(notification.related_status, status)
+ def test_handle_self_boost(self, _):
+ """ boost your own status """
+ view = views.Boost.as_view()
+ request = self.factory.post("")
+ request.user = self.local_user
+ with patch("bookwyrm.activitystreams.ActivityStream.add_status"):
+ status = models.Status.objects.create(user=self.local_user, content="hi")
+
+ view(request, status.id)
+
+ boost = models.Boost.objects.get()
+ self.assertEqual(boost.boosted_status, status)
+ self.assertEqual(boost.user, self.local_user)
+ self.assertEqual(boost.privacy, "public")
+
+ self.assertFalse(models.Notification.objects.exists())
+
def test_handle_boost_unlisted(self, _):
""" boost a status """
view = views.Boost.as_view()
@@ -135,23 +152,21 @@ class InteractionViews(TestCase):
view(request, status.id)
self.assertEqual(models.Boost.objects.count(), 1)
- def test_handle_unboost(self, broadcast_mock):
+ def test_handle_unboost(self, _):
""" undo a boost """
view = views.Unboost.as_view()
request = self.factory.post("")
- request.user = self.local_user
+ request.user = self.remote_user
with patch("bookwyrm.activitystreams.ActivityStream.add_status"):
status = models.Status.objects.create(user=self.local_user, content="hi")
views.Boost.as_view()(request, status.id)
self.assertEqual(models.Boost.objects.count(), 1)
self.assertEqual(models.Notification.objects.count(), 1)
- broadcast_mock.call_count = 0
with patch(
"bookwyrm.activitystreams.ActivityStream.remove_status"
) as redis_mock:
view(request, status.id)
- self.assertEqual(broadcast_mock.call_count, 1)
self.assertTrue(redis_mock.called)
self.assertEqual(models.Boost.objects.count(), 0)
self.assertEqual(models.Notification.objects.count(), 0)