kopia lustrzana https://github.com/jointakahe/takahe
				
				
				
			Follows page
							rodzic
							
								
									adf2449d37
								
							
						
					
					
						commit
						b3072c81ba
					
				|  | @ -335,6 +335,18 @@ nav a i { | ||||||
|     font-size: 200%; |     font-size: 200%; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .icon-menu .option .handle { | ||||||
|  |     margin-right: 20px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .icon-menu .option .pill { | ||||||
|  |     display: inline-block; | ||||||
|  |     padding: 5px 8px; | ||||||
|  |     background: var(--color-highlight); | ||||||
|  |     border-radius: 5px; | ||||||
|  |     margin: 0 5px 0 5px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .handle { | .handle { | ||||||
|     vertical-align: middle; |     vertical-align: middle; | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|  | @ -375,6 +387,20 @@ form.follow { | ||||||
|     float: right; |     float: right; | ||||||
|     margin: 20px 0 0 0; |     margin: 20px 0 0 0; | ||||||
|     font-size: 16px; |     font-size: 16px; | ||||||
|  |     text-align: center; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | form.follow.has-reverse { | ||||||
|  |     margin-top: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | form.follow .reverse-follow { | ||||||
|  |     display: block; | ||||||
|  |     margin: 0 0 5px 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | form.follow button { | ||||||
|  |     margin: 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| form h1 { | form h1 { | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ from django.views.static import serve | ||||||
| from activities.views import posts, search, timelines | from activities.views import posts, search, timelines | ||||||
| from core import views as core | from core import views as core | ||||||
| from stator import views as stator | from stator import views as stator | ||||||
| from users.views import activitypub, admin, auth, identity, settings | from users.views import activitypub, admin, auth, follows, identity, settings | ||||||
| 
 | 
 | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     path("", core.homepage), |     path("", core.homepage), | ||||||
|  | @ -31,6 +31,11 @@ urlpatterns = [ | ||||||
|         settings.ProfilePage.as_view(), |         settings.ProfilePage.as_view(), | ||||||
|         name="settings_profile", |         name="settings_profile", | ||||||
|     ), |     ), | ||||||
|  |     path( | ||||||
|  |         "settings/follows/", | ||||||
|  |         follows.FollowsPage.as_view(), | ||||||
|  |         name="settings_follows", | ||||||
|  |     ), | ||||||
|     path( |     path( | ||||||
|         "settings/interface/", |         "settings/interface/", | ||||||
|         settings.InterfacePage.as_view(), |         settings.InterfacePage.as_view(), | ||||||
|  |  | ||||||
|  | @ -13,16 +13,25 @@ | ||||||
|         <img src="{{ identity.local_icon_url }}" class="icon"> |         <img src="{{ identity.local_icon_url }}" class="icon"> | ||||||
| 
 | 
 | ||||||
|         {% if request.identity %} |         {% if request.identity %} | ||||||
|             <form action="{{ identity.urls.action }}" method="POST" class="inline follow"> |             {% if identity == request.identity %} | ||||||
|                 {% csrf_token %} |                 <form class="inline follow"> | ||||||
|                 {% if follow %} |                     <a class="button" href="{% url "settings_profile" %}">Edit Profile</a> | ||||||
|                     <input type="hidden" name="action" value="unfollow"> |                 </form> | ||||||
|                     <button>Unfollow</button> |             {% else %} | ||||||
|                 {% else %} |                 <form action="{{ identity.urls.action }}" method="POST" class="inline follow {% if reverse_follow %}has-reverse{% endif %}"> | ||||||
|                     <input type="hidden" name="action" value="follow"> |                     {% csrf_token %} | ||||||
|                     <button>Follow</button> |                     {% if reverse_follow %} | ||||||
|                 {% endif %} |                         <span class="reverse-follow">Follows You</span> | ||||||
|             </form> |                     {% endif %} | ||||||
|  |                     {% if follow %} | ||||||
|  |                         <input type="hidden" name="action" value="unfollow"> | ||||||
|  |                         <button>Unfollow</button> | ||||||
|  |                     {% else %} | ||||||
|  |                         <input type="hidden" name="action" value="follow"> | ||||||
|  |                         <button>Follow</button> | ||||||
|  |                     {% endif %} | ||||||
|  |                 </form> | ||||||
|  |             {% endif %} | ||||||
|         {% endif %} |         {% endif %} | ||||||
| 
 | 
 | ||||||
|         {{ identity.name_or_handle }} <small>@{{ identity.handle }}</small> |         {{ identity.name_or_handle }} <small>@{{ identity.handle }}</small> | ||||||
|  |  | ||||||
|  | @ -6,6 +6,9 @@ | ||||||
|     <a href="{% url "settings_interface" %}" {% if section == "interface" %}class="selected"{% endif %}> |     <a href="{% url "settings_interface" %}" {% if section == "interface" %}class="selected"{% endif %}> | ||||||
|         <i class="fa-solid fa-display"></i> Interface |         <i class="fa-solid fa-display"></i> Interface | ||||||
|     </a> |     </a> | ||||||
|  |     <a href="{% url "settings_follows" %}" {% if section == "follows" %}class="selected"{% endif %}> | ||||||
|  |         <i class="fa-solid fa-arrow-right-arrow-left"></i> Follows | ||||||
|  |     </a> | ||||||
|     {% if request.user.admin %} |     {% if request.user.admin %} | ||||||
|     <h3>Account</h3> |     <h3>Account</h3> | ||||||
|     <a href="{% url "settings_security" %}" {% if section == "security" %}class="selected"{% endif %}> |     <a href="{% url "settings_security" %}" {% if section == "security" %}class="selected"{% endif %}> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | {% extends "settings/base.html" %} | ||||||
|  | 
 | ||||||
|  | {% block subtitle %}Follows{% endblock %} | ||||||
|  | 
 | ||||||
|  | {% block content %} | ||||||
|  |     <section class="icon-menu"> | ||||||
|  |         {% for identity, details in identities %} | ||||||
|  |             <a class="option" href="{{ identity.urls.view }}"> | ||||||
|  |                 <img src="{{ identity.local_icon_url }}"> | ||||||
|  |                 <span class="handle"> | ||||||
|  |                     {{ identity.name_or_handle }} | ||||||
|  |                     <small>@{{ identity.handle }}</small> | ||||||
|  |                 </span> | ||||||
|  |                 {% if details.outbound %} | ||||||
|  |                     <span class="pill">Following</span> | ||||||
|  |                 {% endif %} | ||||||
|  |                 {% if details.inbound %} | ||||||
|  |                     <span class="pill">Follows You</span> | ||||||
|  |                 {% endif %} | ||||||
|  |             </a> | ||||||
|  |         {% empty %} | ||||||
|  |             <p class="option empty">You have no follows.</p> | ||||||
|  |         {% endfor %} | ||||||
|  |     </section> | ||||||
|  | {% endblock %} | ||||||
|  | @ -23,6 +23,10 @@ class FollowStates(StateGraph): | ||||||
|     accepted.transitions_to(undone) |     accepted.transitions_to(undone) | ||||||
|     undone.transitions_to(undone_remotely) |     undone.transitions_to(undone_remotely) | ||||||
| 
 | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def group_active(cls): | ||||||
|  |         return [cls.unrequested, cls.local_requested, cls.accepted] | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     async def handle_unrequested(cls, instance: "Follow"): |     async def handle_unrequested(cls, instance: "Follow"): | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | from django.utils.decorators import method_decorator | ||||||
|  | from django.views.generic import TemplateView | ||||||
|  | 
 | ||||||
|  | from users.decorators import identity_required | ||||||
|  | from users.models import FollowStates | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @method_decorator(identity_required, name="dispatch") | ||||||
|  | class FollowsPage(TemplateView): | ||||||
|  |     """ | ||||||
|  |     Shows followers/follows. | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     template_name = "settings/follows.html" | ||||||
|  | 
 | ||||||
|  |     def get_context_data(self): | ||||||
|  |         # Gather all identities with a following relationship with us | ||||||
|  |         identities = {} | ||||||
|  |         for outbound_follow in self.request.identity.outbound_follows.filter( | ||||||
|  |             state__in=FollowStates.group_active() | ||||||
|  |         ): | ||||||
|  |             identities.setdefault(outbound_follow.target, {})[ | ||||||
|  |                 "outbound" | ||||||
|  |             ] = outbound_follow | ||||||
|  |         for inbound_follow in self.request.identity.inbound_follows.filter( | ||||||
|  |             state__in=FollowStates.group_active() | ||||||
|  |         ): | ||||||
|  |             identities.setdefault(inbound_follow.source, {})["inbound"] = inbound_follow | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             "section": "follows", | ||||||
|  |             "identities": sorted(identities.items(), key=lambda i: i[0].username), | ||||||
|  |         } | ||||||
|  | @ -28,18 +28,22 @@ class ViewIdentity(TemplateView): | ||||||
|         if identity.data_age > Config.system.identity_max_age: |         if identity.data_age > Config.system.identity_max_age: | ||||||
|             identity.transition_perform(IdentityStates.outdated) |             identity.transition_perform(IdentityStates.outdated) | ||||||
|         follow = None |         follow = None | ||||||
|  |         reverse_follow = None | ||||||
|         if self.request.identity: |         if self.request.identity: | ||||||
|             follow = Follow.maybe_get(self.request.identity, identity) |             follow = Follow.maybe_get(self.request.identity, identity) | ||||||
|             if follow and follow.state not in [ |             if follow and follow.state not in FollowStates.group_active(): | ||||||
|                 FollowStates.unrequested, |  | ||||||
|                 FollowStates.local_requested, |  | ||||||
|                 FollowStates.accepted, |  | ||||||
|             ]: |  | ||||||
|                 follow = None |                 follow = None | ||||||
|  |             reverse_follow = Follow.maybe_get(identity, self.request.identity) | ||||||
|  |             if ( | ||||||
|  |                 reverse_follow | ||||||
|  |                 and reverse_follow.state not in FollowStates.group_active() | ||||||
|  |             ): | ||||||
|  |                 reverse_follow = None | ||||||
|         return { |         return { | ||||||
|             "identity": identity, |             "identity": identity, | ||||||
|             "posts": posts, |             "posts": posts, | ||||||
|             "follow": follow, |             "follow": follow, | ||||||
|  |             "reverse_follow": reverse_follow, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Ładowanie…
	
		Reference in New Issue
	
	 Andrew Godwin
						Andrew Godwin