Browse Source

Improvements in ignore feature.

Ralfp 12 years ago
parent
commit
e3b439f08e

+ 12 - 0
misago/forums/models.py

@@ -99,6 +99,18 @@ class ForumManager(models.Manager):
                         parents[forum.parent_id].last_poster_slug = forum.last_poster_slug
                         parents[forum.parent_id].last_poster_slug = forum.last_poster_slug
                         parents[forum.parent_id].last_poster_style = forum.last_poster_style
                         parents[forum.parent_id].last_poster_style = forum.last_poster_style
         return forums_list
         return forums_list
+    
+    def ignored_users(self, user, forums):
+        check_ids = []
+        for forum in forums:
+            forum.last_poster_ignored = False
+            if user.is_authenticated() and user.pk != forum.last_poster_id and forum.last_poster_id and not forum.last_poster_id in check_ids:
+                check_ids.append(forum.last_poster_id)
+        ignored_ids = []
+        if check_ids and user.is_authenticated():
+            for user in user.ignores.filter(id__in=check_ids).values('id'):
+                ignored_ids.append(user['id'])
+        print ignored_ids
 
 
 
 
 class Forum(MPTTModel):
 class Forum(MPTTModel):

+ 1 - 0
misago/threads/urls.py

@@ -10,6 +10,7 @@ urlpatterns = patterns('misago.threads.views',
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'NewReplyView', name="thread_new"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'NewReplyView', name="thread_new"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'FirstModeratedView', name="thread_moderated"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'FirstModeratedView', name="thread_moderated"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'FirstReportedView', name="thread_reported"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'FirstReportedView', name="thread_reported"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/show-hidden/$', 'ShowHiddenRepliesView', name="thread_show_hidden"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<page>\d+)/$', 'ThreadView', name="thread"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<page>\d+)/$', 'ThreadView', name="thread"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'PostingView', name="thread_reply", kwargs={'mode': 'new_post'}),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'PostingView', name="thread_reply", kwargs={'mode': 'new_post'}),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<quote>\d+)/reply/$', 'PostingView', name="thread_reply", kwargs={'mode': 'new_post'}),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<quote>\d+)/reply/$', 'PostingView', name="thread_reply", kwargs={'mode': 'new_post'}),

+ 17 - 0
misago/threads/views/jumps.py

@@ -1,8 +1,12 @@
 from django.core.urlresolvers import reverse
 from django.core.urlresolvers import reverse
 from django.shortcuts import redirect
 from django.shortcuts import redirect
 from django.template import RequestContext
 from django.template import RequestContext
+from django.utils.translation import ugettext as _
 from misago.acl.utils import ACLError403, ACLError404
 from misago.acl.utils import ACLError403, ACLError404
+from misago.authn.decorators import block_guest
+from misago.csrf.decorators import check_csrf
 from misago.forums.models import Forum
 from misago.forums.models import Forum
+from misago.messages import Message
 from misago.readstracker.trackers import ThreadsTracker
 from misago.readstracker.trackers import ThreadsTracker
 from misago.threads.models import Thread, Post
 from misago.threads.models import Thread, Post
 from misago.threads.views.base import BaseView
 from misago.threads.views.base import BaseView
@@ -44,6 +48,19 @@ class JumpView(BaseView):
             return error404(request, e.message)
             return error404(request, e.message)
 
 
 
 
+class ShowHiddenRepliesView(JumpView):
+    def make_jump(self):
+        @block_guest
+        @check_csrf
+        def view(request):
+            ignored_exclusions = request.session.get('unignore_threads', [])
+            ignored_exclusions.append(self.thread.pk)
+            request.session['unignore_threads'] = ignored_exclusions
+            request.messages.set_flash(Message(_('Replies made to this thread by members on your ignore list have been revealed.')), 'success', 'threads')
+            return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
+        return view(self.request)
+
+
 class LastReplyView(JumpView):
 class LastReplyView(JumpView):
     def make_jump(self):
     def make_jump(self):
         return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
         return self.redirect(self.thread.post_set.order_by('-id')[:1][0])

+ 6 - 0
misago/threads/views/list.py

@@ -33,6 +33,10 @@ class ThreadsView(BaseView):
         self.threads = []
         self.threads = []
         queryset_anno = Thread.objects.filter(Q(forum=Forum.objects.token_to_pk('annoucements')) | (Q(forum=self.forum) & Q(weight=2)))
         queryset_anno = Thread.objects.filter(Q(forum=Forum.objects.token_to_pk('annoucements')) | (Q(forum=self.forum) & Q(weight=2)))
         queryset_threads = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last')
         queryset_threads = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last')
+        if self.request.user.is_authenticated():
+            ignored_users = self.request.user.ignored_users()
+            if ignored_users:
+                queryset_threads = queryset_threads.extra(where=["`threads_thread`.`start_poster_id` IS NULL OR `threads_thread`.`start_poster_id` NOT IN (%s)" % ','.join([str(i) for i in ignored_users])])
         if self.request.settings.avatars_on_threads_list:
         if self.request.settings.avatars_on_threads_list:
             queryset_anno = queryset_anno.prefetch_related('start_poster', 'last_post')
             queryset_anno = queryset_anno.prefetch_related('start_poster', 'last_post')
             queryset_threads = queryset_threads.prefetch_related('start_poster', 'last_poster')
             queryset_threads = queryset_threads.prefetch_related('start_poster', 'last_poster')
@@ -44,6 +48,8 @@ class ThreadsView(BaseView):
             self.threads = self.threads[self.pagination['start']:self.pagination['stop']]
             self.threads = self.threads[self.pagination['start']:self.pagination['stop']]
         for thread in self.threads:
         for thread in self.threads:
             thread.is_read = self.tracker.is_read(thread)
             thread.is_read = self.tracker.is_read(thread)
+            thread.last_poster_ignored = thread.last_poster_id in ignored_users
+            
 
 
     def get_thread_actions(self):
     def get_thread_actions(self):
         acl = self.request.acl.threads.get_role(self.forum)
         acl = self.request.acl.threads.get_role(self.forum)

+ 8 - 0
misago/threads/views/thread.py

@@ -39,9 +39,15 @@ class ThreadView(BaseView):
         if self.request.settings.posts_per_page < self.count:
         if self.request.settings.posts_per_page < self.count:
             self.posts = self.posts[self.pagination['start']:self.pagination['stop']]
             self.posts = self.posts[self.pagination['start']:self.pagination['stop']]
         self.read_date = self.tracker.get_read_date(self.thread)
         self.read_date = self.tracker.get_read_date(self.thread)
+        ignored_users = []
+        if self.request.user.is_authenticated():
+            ignored_users = self.request.user.ignored_users()        
         for post in self.posts:
         for post in self.posts:
             post.message = self.request.messages.get_message('threads_%s' % post.pk)
             post.message = self.request.messages.get_message('threads_%s' % post.pk)
             post.is_read = post.date <= self.read_date
             post.is_read = post.date <= self.read_date
+            post.ignored = self.thread.start_post_id != post.pk and not self.thread.pk in self.request.session.get('unignore_threads', []) and post.user_id in ignored_users
+            if post.ignored:
+                self.ignored = True
         last_post = self.posts[len(self.posts) - 1]
         last_post = self.posts[len(self.posts) - 1]
         if not self.tracker.is_read(self.thread):
         if not self.tracker.is_read(self.thread):
             self.tracker.set_read(self.thread, last_post)
             self.tracker.set_read(self.thread, last_post)
@@ -506,6 +512,7 @@ class ThreadView(BaseView):
         self.request = request
         self.request = request
         self.pagination = None
         self.pagination = None
         self.parents = None
         self.parents = None
+        self.ignored = False
         try:
         try:
             self.fetch_thread(thread)
             self.fetch_thread(thread)
             self.fetch_posts(page)
             self.fetch_posts(page)
@@ -537,6 +544,7 @@ class ThreadView(BaseView):
                                                  'is_read': self.tracker.is_read(self.thread),
                                                  'is_read': self.tracker.is_read(self.thread),
                                                  'count': self.count,
                                                  'count': self.count,
                                                  'posts': self.posts,
                                                  'posts': self.posts,
+                                                 'ignored_posts': self.ignored,
                                                  'pagination': self.pagination,
                                                  'pagination': self.pagination,
                                                  'quick_reply': FormFields(QuickReplyForm(request=request)).fields,
                                                  'quick_reply': FormFields(QuickReplyForm(request=request)).fields,
                                                  'thread_form': FormFields(self.thread_form).fields if self.thread_form else None,
                                                  'thread_form': FormFields(self.thread_form).fields if self.thread_form else None,

+ 3 - 0
misago/users/models.py

@@ -388,6 +388,9 @@ class User(models.Model):
             return self.ignores.filter(id=user.pk).count() > 0
             return self.ignores.filter(id=user.pk).count() > 0
         except AttributeError:
         except AttributeError:
             return self.ignores.filter(id=user).count() > 0
             return self.ignores.filter(id=user).count() > 0
+        
+    def ignored_users(self):
+        return [item['id'] for item in self.ignores.values('id')]
 
 
     def get_roles(self):
     def get_roles(self):
         return self.roles.all()
         return self.roles.all()

+ 8 - 2
misago/views.py

@@ -45,11 +45,17 @@ def home(request):
             del users_list
             del users_list
         cache.set('ranks_list', ranks_list, 300)
         cache.set('ranks_list', ranks_list, 300)
 
 
-    # Render page with forums list
+    # Load reads tracker and build forums list
     reads_tracker = ForumsTracker(request.user)
     reads_tracker = ForumsTracker(request.user)
+    forums_list = Forum.objects.treelist(request.acl.forums, tracker=reads_tracker)
+    
+    # Whitelist ignored members
+    Forum.objects.ignored_users(request.user, forums_list)
+        
+    # Render page 
     return request.theme.render_to_response('index.html',
     return request.theme.render_to_response('index.html',
                                             {
                                             {
-                                             'forums_list': Forum.objects.treelist(request.acl.forums, tracker=reads_tracker),
+                                             'forums_list': forums_list,
                                              'ranks_online': ranks_list,
                                              'ranks_online': ranks_list,
                                              'popular_threads': popular_threads,
                                              'popular_threads': popular_threads,
                                              },
                                              },

+ 3 - 0
static/sora/css/sora.css

@@ -910,12 +910,15 @@ td.lead-cell{color:#555555;font-weight:bold;}
 .sidetabs-content{padding-top:0px;margin-top:-12px;}
 .sidetabs-content{padding-top:0px;margin-top:-12px;}
 .list-nav{overflow:auto;margin-bottom:4px;}.list-nav .nav-pills{margin:0px;}
 .list-nav{overflow:auto;margin-bottom:4px;}.list-nav .nav-pills{margin:0px;}
 .list-nav.last{margin-top:-8px;}
 .list-nav.last{margin-top:-8px;}
+.list-nav button,.list-nav button:hover,.list-nav button:active{border:none;margin:0px;position:relative;top:2px;padding:6px 12px;padding-bottom:5px;}
 .nav-pills li{margin-left:8px;}.nav-pills li form{margin:0px;padding:0px;}
 .nav-pills li{margin-left:8px;}.nav-pills li form{margin:0px;padding:0px;}
 .nav-pills li button,.nav-pills li button:hover,.nav-pills li button:active{border:none;}
 .nav-pills li button,.nav-pills li button:hover,.nav-pills li button:active{border:none;}
 .nav-pills li.info a:link,.nav-pills li.danger a:link,.nav-pills li.primary a:link,.nav-pills li.success a:link,.nav-pills li.info a:visited,.nav-pills li.danger a:visited,.nav-pills li.primary a:visited,.nav-pills li.success a:visited{font-weight:bold;}
 .nav-pills li.info a:link,.nav-pills li.danger a:link,.nav-pills li.primary a:link,.nav-pills li.success a:link,.nav-pills li.info a:visited,.nav-pills li.danger a:visited,.nav-pills li.primary a:visited,.nav-pills li.success a:visited{font-weight:bold;}
 .nav-pills li.info a:link,.nav-pills li.info a:visited,.nav-pills li.info button{background-color:#eeeeee;color:#555555;}.nav-pills li.info a:link i,.nav-pills li.info a:visited i,.nav-pills li.info button i{opacity:0.6;filter:alpha(opacity=60);}
 .nav-pills li.info a:link,.nav-pills li.info a:visited,.nav-pills li.info button{background-color:#eeeeee;color:#555555;}.nav-pills li.info a:link i,.nav-pills li.info a:visited i,.nav-pills li.info button i{opacity:0.6;filter:alpha(opacity=60);}
 .nav-pills li.info a:active,.nav-pills li.info a:hover,.nav-pills li.info button:active,.nav-pills li.info button:hover{background-color:#555555 !important;color:#ffffff;}.nav-pills li.info a:active i,.nav-pills li.info a:hover i,.nav-pills li.info button:active i,.nav-pills li.info button:hover i{background-image:url("../img/glyphicons-halflings-white.png");opacity:1;filter:alpha(opacity=100);}
 .nav-pills li.info a:active,.nav-pills li.info a:hover,.nav-pills li.info button:active,.nav-pills li.info button:hover{background-color:#555555 !important;color:#ffffff;}.nav-pills li.info a:active i,.nav-pills li.info a:hover i,.nav-pills li.info button:active i,.nav-pills li.info button:hover i{background-image:url("../img/glyphicons-halflings-white.png");opacity:1;filter:alpha(opacity=100);}
 .nav-pills li.danger a:link,.nav-pills li.primary a:link,.nav-pills li.success a:link,.nav-pills li.danger a:visited,.nav-pills li.primary a:visited,.nav-pills li.success a:visited,.nav-pills li.danger button,.nav-pills li.primary button,.nav-pills li.success button{color:#ffffff;}.nav-pills li.danger a:link i,.nav-pills li.primary a:link i,.nav-pills li.success a:link i,.nav-pills li.danger a:visited i,.nav-pills li.primary a:visited i,.nav-pills li.success a:visited i,.nav-pills li.danger button i,.nav-pills li.primary button i,.nav-pills li.success button i{background-image:url("../img/glyphicons-halflings-white.png");}
 .nav-pills li.danger a:link,.nav-pills li.primary a:link,.nav-pills li.success a:link,.nav-pills li.danger a:visited,.nav-pills li.primary a:visited,.nav-pills li.success a:visited,.nav-pills li.danger button,.nav-pills li.primary button,.nav-pills li.success button{color:#ffffff;}.nav-pills li.danger a:link i,.nav-pills li.primary a:link i,.nav-pills li.success a:link i,.nav-pills li.danger a:visited i,.nav-pills li.primary a:visited i,.nav-pills li.success a:visited i,.nav-pills li.danger button i,.nav-pills li.primary button i,.nav-pills li.success button i{background-image:url("../img/glyphicons-halflings-white.png");}
+.nav-pills li.discourage a:link,.nav-pills li.discourage a:visited,.nav-pills li.discourage button{background-color:#eeeeee;opacity:0.4;filter:alpha(opacity=40);color:#333333;}
+.nav-pills li.discourage a:active,.nav-pills li.discourage a:hover,.nav-pills li.discourage button:active,.nav-pills li.discourage button:hover{opacity:0.8;filter:alpha(opacity=80);}
 .nav-pills li.danger a:link,.nav-pills li.danger a:visited,.nav-pills li.danger button{background-color:#dc4e44 !important;}
 .nav-pills li.danger a:link,.nav-pills li.danger a:visited,.nav-pills li.danger button{background-color:#dc4e44 !important;}
 .nav-pills li.danger a:active,.nav-pills li.danger a:hover,.nav-pills li.danger button:active,.nav-pills li.danger button:hover{background-color:#9d261d !important;}
 .nav-pills li.danger a:active,.nav-pills li.danger a:hover,.nav-pills li.danger button:active,.nav-pills li.danger button:hover{background-color:#9d261d !important;}
 .nav-pills li.primary a:link,.nav-pills li.primary a:visited,.nav-pills li.primary button{background-color:#0da6f2 !important;}
 .nav-pills li.primary a:link,.nav-pills li.primary a:visited,.nav-pills li.primary button{background-color:#0da6f2 !important;}

+ 22 - 0
static/sora/css/sora/navs.less

@@ -102,6 +102,15 @@
   &.last {
   &.last {
     margin-top: -8px;
     margin-top: -8px;
   }
   }
+    
+  button, button:hover, button:active {
+    border: none;
+    margin: 0px;
+    position: relative;
+    top: 2px;
+    padding: 6px 12px;
+    padding-bottom: 5px;
+  }
 }
 }
 
 
 // Pills
 // Pills
@@ -156,6 +165,19 @@
       }
       }
     }
     }
     
     
+    &.discourage {
+      a:link, a:visited, button {
+        background-color: @grayLighter;
+        .opacity(40);
+        
+        color: @grayDark;
+      }
+      
+      a:active, a:hover, button:active, button:hover {
+        .opacity(80);
+      }
+    }
+    
     &.danger {
     &.danger {
       a:link, a:visited, button {
       a:link, a:visited, button {
         background-color: lighten(@red, 20%) !important;
         background-color: lighten(@red, 20%) !important;

+ 12 - 2
templates/sora/threads/list.html

@@ -72,9 +72,19 @@
           {% if thread.deleted %}<li><span class="tooltip-top" title="{% trans %}This thread has been deleted.{% endtrans %}"><i class="icon-remove"></i></span></li>{% endif %}
           {% if thread.deleted %}<li><span class="tooltip-top" title="{% trans %}This thread has been deleted.{% endtrans %}"><i class="icon-remove"></i></span></li>{% endif %}
         </ul>
         </ul>
       </td>
       </td>
-      <td class="span3 thread-author"><span class="tooltip-top" title="{{ thread.start|reltimesince }}">{% if thread.start_poster_id %}{% if settings.avatars_on_threads_list %}<img src="{{ thread.start_poster.get_avatar(24) }}" alt="" class="avatar-tiny"> {% endif %}<a href="{% url 'user' user=thread.start_poster_id, username=thread.start_poster_slug %}">{{ thread.start_poster_name }}</a>{% else %}{% if settings.avatars_on_threads_list %}<img src="{{ macros.avatar_guest(24) }}" alt="" class="avatar-tiny"> {% endif %}<em class="muted">{{ thread.start_poster_name }}</em>{% endif %}</span></td>
+      <td class="span3 thread-author"><span class="tooltip-top" title="{{ thread.start|reltimesince }}">{% if thread.start_poster_id -%}
+          {% if settings.avatars_on_threads_list %}<img src="{{ thread.start_poster.get_avatar(24) }}" alt="" class="avatar-tiny"> {% endif %}<a href="{% url 'user' user=thread.start_poster_id, username=thread.start_poster_slug %}">{{ thread.start_poster_name }}</a>
+          {%- else -%}
+          {% if settings.avatars_on_threads_list %}<img src="{{ macros.avatar_guest(24) }}" alt="" class="avatar-tiny"> {% endif %}<em class="muted">{{ thread.start_poster_name }}</em>
+      {% endif %}</span></td>
       <td class="span1 thread-stat">{{ thread.replies|intcomma }}</td>
       <td class="span1 thread-stat">{{ thread.replies|intcomma }}</td>
-      <td class="span3 thread-poster"><span class="tooltip-top" title="{{ thread.last|reltimesince }}">{% if thread.last_poster_id %}{% if settings.avatars_on_threads_list %}<img src="{{ thread.last_poster.get_avatar(24) }}" alt="" class="avatar-tiny"> {% endif %}<a href="{% url 'user' user=thread.last_poster_id, username=thread.last_poster_slug %}">{{ thread.last_poster_name }}</a>{% else %}{% if settings.avatars_on_threads_list %}<img src="{{ macros.avatar_guest(24) }}" alt="" class="avatar-tiny"> {% endif %}<em class="muted">{{ thread.last_poster_name }}</em>{% endif %}</span></td>
+      <td class="span3 thread-poster"><span class="tooltip-top" title="{{ thread.last|reltimesince }}">{% if thread.last_poster_ignored -%}
+          {% if settings.avatars_on_threads_list %}<img src="{{ macros.avatar_guest(24) }}" alt="" class="avatar-tiny"> {% endif %}<em class="muted">{% trans %}Ignored Member{% endtrans %}</em>
+          {%- elif thread.last_poster_id -%}
+          {% if settings.avatars_on_threads_list %}<img src="{{ thread.last_poster.get_avatar(24) }}" alt="" class="avatar-tiny"> {% endif %}<a href="{% url 'user' user=thread.last_poster_id, username=thread.last_poster_slug %}">{{ thread.last_poster_name }}</a>
+          {%- else -%}
+          {% if settings.avatars_on_threads_list %}<img src="{{ macros.avatar_guest(24) }}" alt="" class="avatar-tiny"> {% endif %}<em class="muted">{{ thread.last_poster_name }}</em>
+          {%- endif %}</span></td>
       {% if user.is_authenticated() and list_form %}
       {% if user.is_authenticated() and list_form %}
       <td class="check-cell">{% if thread.forum_id == forum.pk %}<label class="checkbox"><input form="threads_form" name="{{ list_form['list_items']['html_name'] }}" type="checkbox" class="checkbox-member" value="{{ thread.pk }}"{% if list_form['list_items']['has_value'] and ('' ~ thread.pk) in list_form['list_items']['value'] %} checked="checked"{% endif %}></label>{% else %}&nbsp;{% endif %}</td>
       <td class="check-cell">{% if thread.forum_id == forum.pk %}<label class="checkbox"><input form="threads_form" name="{{ list_form['list_items']['html_name'] }}" type="checkbox" class="checkbox-member" value="{{ thread.pk }}"{% if list_form['list_items']['has_value'] and ('' ~ thread.pk) in list_form['list_items']['value'] %} checked="checked"{% endif %}></label>{% else %}&nbsp;{% endif %}</td>
       {% endif %}
       {% endif %}

+ 21 - 2
templates/sora/threads/thread.html

@@ -36,8 +36,9 @@
   {{ pager() }}
   {{ pager() }}
   {% if user.is_authenticated() %}
   {% if user.is_authenticated() %}
   <ul class="nav nav-pills pull-right">
   <ul class="nav nav-pills pull-right">
+    {% if ignored_posts %}<li class="discourage"><form action="{% url 'thread_show_hidden' thread=thread.pk, slug=thread.slug %}" class="form-inline" method="post"><input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}"><button type="submit" class="btn"><i class="icon-eye-open"></i> {% trans %}Show Hidden Replies{% endtrans %}</button></form></li>{% endif %}
     <li class="info"><a href="{% url 'thread_new' forum=forum.pk, slug=forum.slug %}"><i class="icon-ok"></i> {% trans %}Watch Thread{% endtrans %}</a></li>{% if acl.threads.can_reply(forum, thread) %}
     <li class="info"><a href="{% url 'thread_new' forum=forum.pk, slug=forum.slug %}"><i class="icon-ok"></i> {% trans %}Watch Thread{% endtrans %}</a></li>{% if acl.threads.can_reply(forum, thread) %}
-    <li class="primary"><a href="{% url 'thread_reply' thread=thread.pk, slug=thread.slug %}"><i class="icon-plus"></i> {% trans %}Reply{% endtrans %}</a></li>{% endif %}
+    <li class="primary"><a href="{% url 'thread_reply' thread=thread.pk, slug=thread.slug %}"><i class="icon-pencil"></i> {% trans %}Reply{% endtrans %}</a></li>{% endif %}
   </ul>
   </ul>
   {% endif %}
   {% endif %}
 </div>
 </div>
@@ -67,6 +68,24 @@
       {% trans user=edit_user(post), date=post.edit_date|reltimesince|low %}{{ user }} has deleted this reply {{ date }}{% endtrans %}
       {% trans user=edit_user(post), date=post.edit_date|reltimesince|low %}{{ user }} has deleted this reply {{ date }}{% endtrans %}
     </div>
     </div>
   </div>
   </div>
+  {% elif post.ignored %}
+  <div id="post-{{ post.pk }}" class="well well-post well-post-deleted{% if post.user and post.user.rank and post.user.rank.style %} {{ post.user.rank.style }}{% endif %}">
+    <div class="post-author">
+      <div class="post-bit">
+        <span class="lead">{% trans %}Hidden Reply{% endtrans %}</span>
+      </div>
+    </div>
+    <div class="post-extra">
+      <a href="{% if pagination['page'] > 1 -%}
+      {% url 'thread' thread=thread.pk, slug=thread.slug, page=pagination['page'] %}
+      {%- else -%}
+      {% url 'thread' thread=thread.pk, slug=thread.slug %}
+      {%- endif %}#post-{{ post.pk }}" class="post-perma pull-right tooltip-left" title="{% trans %}Direct link to this post{% endtrans %}">#{{ pagination['start'] + loop.index }}</a>
+    </div>
+    <div class="post-content">
+      {% trans user=yabadaba %}This reply was posted by user that is on your ignored list.{% endtrans %}
+    </div>
+  </div>
   {% else %}
   {% else %}
   <div id="post-{{ post.pk }}" class="well well-post{% if post.user and post.user.rank and post.user.rank.style %} {{ post.user.rank.style }}{% endif %}">
   <div id="post-{{ post.pk }}" class="well well-post{% if post.user and post.user.rank and post.user.rank.style %} {{ post.user.rank.style }}{% endif %}">
     <div class="post-author">
     <div class="post-author">
@@ -221,7 +240,7 @@
   {{ pager(false) }}
   {{ pager(false) }}
   {% if user.is_authenticated() and acl.threads.can_reply(forum, thread) %}
   {% if user.is_authenticated() and acl.threads.can_reply(forum, thread) %}
   <ul class="nav nav-pills pull-right">
   <ul class="nav nav-pills pull-right">
-    <li class="primary"><a href="{% url 'thread_reply' thread=thread.pk, slug=thread.slug %}"><i class="icon-plus"></i> {% trans %}Reply{% endtrans %}</a></li>
+    <li class="primary"><a href="{% url 'thread_reply' thread=thread.pk, slug=thread.slug %}"><i class="icon-pencil"></i> {% trans %}Reply{% endtrans %}</a></li>
   </ul>
   </ul>
   {% endif %}
   {% endif %}
 </div>
 </div>