mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-26 19:41:11 +00:00
commit
bdde69473a
9 changed files with 164 additions and 127 deletions
Binary file not shown.
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 23 KiB |
Binary file not shown.
Binary file not shown.
|
@ -1,10 +1,10 @@
|
|||
@font-face {
|
||||
font-family: 'icomoon';
|
||||
src: url('fonts/icomoon.eot?v0wquk');
|
||||
src: url('fonts/icomoon.eot?v0wquk#iefix') format('embedded-opentype'),
|
||||
url('fonts/icomoon.ttf?v0wquk') format('truetype'),
|
||||
url('fonts/icomoon.woff?v0wquk') format('woff'),
|
||||
url('fonts/icomoon.svg?v0wquk#icomoon') format('svg');
|
||||
src: url('fonts/icomoon.eot?7ifunb');
|
||||
src: url('fonts/icomoon.eot?7ifunb#iefix') format('embedded-opentype'),
|
||||
url('fonts/icomoon.ttf?7ifunb') format('truetype'),
|
||||
url('fonts/icomoon.woff?7ifunb') format('woff'),
|
||||
url('fonts/icomoon.svg?7ifunb#icomoon') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
|
@ -13,7 +13,7 @@
|
|||
[class^="icon-"], [class*=" icon-"] {
|
||||
/* use !important to prevent issues with browser extensions that change fonts */
|
||||
font-family: 'icomoon' !important;
|
||||
speak: none;
|
||||
speak: never;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
|
@ -25,26 +25,71 @@
|
|||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-arrow-right:before {
|
||||
.icon-envelope:before {
|
||||
content: "\e900";
|
||||
}
|
||||
.icon-arrow-left:before {
|
||||
content: "\e910";
|
||||
.icon-arrow-right:before {
|
||||
content: "\e901";
|
||||
}
|
||||
.icon-arrow-up:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.icon-arrow-down:before {
|
||||
content: "\e912";
|
||||
.icon-bell:before {
|
||||
content: "\e902";
|
||||
}
|
||||
.icon-x:before {
|
||||
content: "\e902";
|
||||
content: "\e903";
|
||||
}
|
||||
.icon-cancel:before {
|
||||
content: "\e902";
|
||||
.icon-quote-close:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.icon-close:before {
|
||||
content: "\e902";
|
||||
.icon-quote-open:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-image:before {
|
||||
content: "\e906";
|
||||
}
|
||||
.icon-pencil:before {
|
||||
content: "\e907";
|
||||
}
|
||||
.icon-list:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.icon-unlock:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-globe:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-lock:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.icon-chain-broken:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.icon-chain:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.icon-comments:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.icon-comment:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.icon-boost:before {
|
||||
content: "\e910";
|
||||
}
|
||||
.icon-arrow-left:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.icon-arrow-up:before {
|
||||
content: "\e912";
|
||||
}
|
||||
.icon-arrow-down:before {
|
||||
content: "\e913";
|
||||
}
|
||||
.icon-home:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.icon-local:before {
|
||||
content: "\e915";
|
||||
}
|
||||
.icon-search:before {
|
||||
content: "\e986";
|
||||
|
@ -61,78 +106,3 @@
|
|||
.icon-heart:before {
|
||||
content: "\e9da";
|
||||
}
|
||||
.icon-local:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.icon-home:before {
|
||||
content: "\e913";
|
||||
}
|
||||
.icon-quote-close:before {
|
||||
content: "\e903";
|
||||
}
|
||||
.icon-quote-open:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.icon-image:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-photo:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-picture-o:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-pencil:before {
|
||||
content: "\e906";
|
||||
}
|
||||
.icon-list:before {
|
||||
content: "\e907";
|
||||
}
|
||||
.icon-unlock:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.icon-unlisted:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.icon-globe:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-global:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-federated:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-public:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-lock:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-private:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-chain-broken:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.icon-unlink:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.icon-chain:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.icon-link:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.icon-comments:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.icon-comment:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.icon-boost:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.icon-bell:before {
|
||||
content: "\e901";
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
{% csrf_token %}
|
||||
<input type="hidden" name="book" value="{{ book.id }}">
|
||||
<input type="hidden" name="user" value="{{ request.user.id }}">
|
||||
<input type="hidden" name="privacy" value="public">
|
||||
<div class="control">
|
||||
<label class="label" for="id_name_{{ book.id }}_review">Title:</label>
|
||||
<input type="text" name="name" maxlength="255" class="input" required="" id="id_name_{{ book.id }}_review" placeholder="My review of '{{ book.title }}'">
|
||||
|
@ -44,7 +43,17 @@
|
|||
|
||||
<textarea name="content" class="textarea" id="id_content_{{ book.id }}_review"></textarea>
|
||||
</div>
|
||||
<button class="button is-primary" type="submit">post review</button>
|
||||
<div class="control is-grouped">
|
||||
<div class="select">
|
||||
<select name="privacy">
|
||||
<option value="public" selected>Public</option>
|
||||
<option value="unlisted">Unlisted</option>
|
||||
<option value="followers">Followers only</option>
|
||||
<option value="direct">Private</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="button is-primary" type="submit">post review</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@ -60,7 +69,17 @@
|
|||
<label class="label" for="id_content_{{ book.id }}_comment">Comment:</label>
|
||||
<textarea name="content" class="textarea" id="id_content_{{ book.id }}_comment" placeholder="Some thoughts on '{{ book.title }}'"></textarea>
|
||||
</div>
|
||||
<button class="button is-primary" type="submit">post comment</button>
|
||||
<div class="control is-grouped">
|
||||
<div class="select">
|
||||
<select name="privacy">
|
||||
<option value="public" selected>Public</option>
|
||||
<option value="unlisted">Unlisted</option>
|
||||
<option value="followers">Followers only</option>
|
||||
<option value="direct">Private</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="button is-primary" type="submit">post comment</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@ -80,7 +99,17 @@
|
|||
<label class="label" for="id_content_{{ book.id }}_quote">Comment:</label>
|
||||
<textarea name="content" class="textarea is-small" id="id_content_{{ book.id }}_quote"></textarea>
|
||||
</div>
|
||||
<button class="button is-primary" type="submit">post quote</button>
|
||||
<div class="control is-grouped">
|
||||
<div class="select">
|
||||
<select name="privacy">
|
||||
<option value="public" selected>Public</option>
|
||||
<option value="unlisted">Unlisted</option>
|
||||
<option value="followers">Followers only</option>
|
||||
<option value="direct">Private</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="button is-primary" type="submit">post quote</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% csrf_token %}
|
||||
<input type="hidden" name="reply_parent" value="{{ activity.id }}">
|
||||
<input type="hidden" name="user" value="{{ request.user.id }}">
|
||||
<input type="hidden" name="privacy" value="public">
|
||||
<input type="hidden" name="privacy" value="{{ activity.privacy }}">
|
||||
<textarea name="content" placeholder="Leave a comment..." id="id_content_{{ activity.id }}" required="true"></textarea>
|
||||
<button class="button" type="submit">
|
||||
<span class="icon icon-comment">
|
||||
|
|
|
@ -23,15 +23,29 @@
|
|||
{% endif %}
|
||||
|
||||
<div class="card-footer-item">
|
||||
<span class="icon icon-public">
|
||||
{% if status.privacy == 'public' %}
|
||||
<span class="icon icon-globe">
|
||||
<span class="is-sr-only">Public post</span>
|
||||
</span>
|
||||
{% elif status.privacy == 'unlisted' %}
|
||||
<span class="icon icon-unlock">
|
||||
<span class="is-sr-only">Unlisted post</span>
|
||||
</span>
|
||||
{% elif status.privacy == 'followers' %}
|
||||
<span class="icon icon-lock">
|
||||
<span class="is-sr-only">Followers-only post</span>
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="icon icon-envelope">
|
||||
<span class="is-sr-only">Private post</span>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if status.user == request.user %}
|
||||
<form name="delete-{{status.id}}" action="/delete-status" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="status" value="{{ status.id }}">
|
||||
<button type="submit">
|
||||
<span class="icon icon-cancel">
|
||||
<span class="icon icon-x">
|
||||
<span class="is-sr-only">Delete post</span>
|
||||
</span>
|
||||
</button>
|
||||
|
|
|
@ -130,17 +130,22 @@ def get_activity_feed(user, filter_level, model=models.Status):
|
|||
if filter_level in ['friends', 'home']:
|
||||
# people you follow and direct mentions
|
||||
activities = activities.filter(
|
||||
Q(user__in=following, privacy='public') | \
|
||||
Q(mention_users=user)
|
||||
Q(user__in=following, privacy__in=['public', 'unlisted', 'followers']) | \
|
||||
Q(mention_users=user) | Q(user=user)
|
||||
)
|
||||
elif filter_level == 'self':
|
||||
activities = activities.filter(user=user, privacy='public')
|
||||
elif filter_level == 'local':
|
||||
# everyone on this instance
|
||||
activities = activities.filter(user__local=True, privacy='public')
|
||||
# everyone on this instance except unlisted
|
||||
activities = activities.filter(
|
||||
Q(user__in=following, privacy='followers') | Q(privacy='public'),
|
||||
user__local=True
|
||||
)
|
||||
else:
|
||||
# all activities from everyone you federate with
|
||||
activities = activities.filter(privacy='public')
|
||||
activities = activities.filter(
|
||||
Q(user__in=following, privacy='followers') | Q(privacy='public')
|
||||
)
|
||||
|
||||
return activities
|
||||
|
||||
|
@ -386,9 +391,14 @@ def status_page(request, username, status_id):
|
|||
except ValueError:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
# the url should have the poster's username in it
|
||||
if user != status.user:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
# make sure the user is authorized to see the status
|
||||
if not status_visible_to_user(request.user, status):
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if is_api_request(request):
|
||||
return JsonResponse(status.to_activity(), encoder=ActivityEncoder)
|
||||
|
||||
|
@ -397,6 +407,19 @@ def status_page(request, username, status_id):
|
|||
}
|
||||
return TemplateResponse(request, 'status.html', data)
|
||||
|
||||
def status_visible_to_user(viewer, status):
|
||||
''' is a user authorized to view a status? '''
|
||||
if viewer == status.user or status.privacy in ['public', 'unlisted']:
|
||||
return True
|
||||
if status.privacy == 'followers' and \
|
||||
status.user.followers.filter(id=viewer.id).first():
|
||||
return True
|
||||
if status.privacy == 'direct' and \
|
||||
status.mention_users.filter(id=viewer.id).first():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
def replies_page(request, username, status_id):
|
||||
|
|
Loading…
Reference in a new issue