39398a1f78
* On Forums and photo comment threads: display the poster's username below their display name, if their username differs. If they do not have a distinct display name, a small @ appears in front of their display name instead. * On Quote & Reply, wrap the @mention with a Markdown hyperlink to the specific comment ID.
435 lines
22 KiB
HTML
435 lines
22 KiB
HTML
{{define "title"}}Photo: {{or .Photo.Caption "No caption"}}{{end}}
|
|
{{define "content"}}
|
|
<div class="container">
|
|
<section class="hero is-link is-bold">
|
|
<div class="hero-body">
|
|
<div class="container">
|
|
<h1 class="title">
|
|
<span class="icon mr-4">
|
|
<i class="fa fa-image"></i>
|
|
</span>
|
|
<span>{{or .Photo.Caption "Photo"}}</span>
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{{ $Root := . }}
|
|
{{ $User := .CurrentUser }}
|
|
{{ $Comments := .CommentMap.Get .Photo.ID }}
|
|
|
|
<div class="block p-4">
|
|
<nav class="breadcrumb" aria-label="breadcrumbs">
|
|
<ul>
|
|
<li>
|
|
<a href="/u/{{.User.Username}}">
|
|
<span class="icon"><i class="fa fa-user"></i></span>
|
|
<span>{{.User.Username}}</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/u/{{.User.Username}}/photos">Photos</a>
|
|
</li>
|
|
<li class="is-active">
|
|
<a href="{{.Request.URL.Path}}" aria-current="page">Comments</a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="block p-4">
|
|
|
|
<!-- Photo Card -->
|
|
<div class="card block">
|
|
<header class="card-header {{if .Photo.Explicit}}has-background-danger{{else}}has-background-link{{end}}">
|
|
<div class="card-header-title has-text-light">
|
|
<div class="columns is-mobile is-gapless nonshy-fullwidth">
|
|
<div class="column is-narrow mr-2">
|
|
{{template "avatar-24x24" .User}}
|
|
</div>
|
|
<div class="column">
|
|
<a href="/u/{{.User.Username}}" class="has-text-light">
|
|
{{.User.Username}}
|
|
<i class="fa fa-external-link ml-2"></i>
|
|
</a>
|
|
</div>
|
|
<div class="column is-narrow">
|
|
<span class="icon">
|
|
{{if eq .Photo.Visibility "friends"}}
|
|
<i class="fa fa-user-group has-text-warning" title="Friends"></i>
|
|
{{else if eq .Photo.Visibility "private"}}
|
|
<i class="fa fa-lock has-text-private-light" title="Private"></i>
|
|
{{else}}
|
|
<i class="fa fa-eye has-text-link-light" title="Public"></i>
|
|
{{end}}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="card-image has-text-centered is-clipped">
|
|
<!-- GIF video? -->
|
|
{{if HasSuffix .Photo.Filename ".mp4"}}
|
|
<video loop controls controlsList="nodownload" playsinline
|
|
{{if .Photo.AltText}}title="{{.Photo.AltText}}"{{end}}
|
|
{{if BlurExplicit .Photo}}class="blurred-explicit"
|
|
{{else if (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay
|
|
{{end}}>
|
|
<source src="{{PhotoURL .Photo.Filename}}" type="video/mp4">
|
|
</video>
|
|
{{else}}
|
|
<img src="{{PhotoURL .Photo.Filename}}"
|
|
{{if BlurExplicit .Photo}} class="blurred-explicit"{{end}}
|
|
{{if .Photo.AltText}}alt="{{.Photo.AltText}}" title="{{.Photo.AltText}}"{{end}}>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="card-content">
|
|
{{if .Photo.Caption}}
|
|
{{.Photo.Caption}}
|
|
{{else}}<em>No caption</em>{{end}}
|
|
|
|
<!-- Alt Text -->
|
|
{{if .Photo.AltText}}
|
|
<div class="box my-4 py-3 px-4 is-size-7">
|
|
<strong class="tag is-grey mr-2 cursor-default">Alt Text</strong>
|
|
<span class="line-breakable">{{.Photo.AltText}}</span>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- Timestamp -->
|
|
<div>
|
|
<span class="tag is-grey is-light has-text-dark mr-2">
|
|
<span class="icon">
|
|
<i class="fa fa-eye"></i>
|
|
</span>
|
|
<span>{{.Photo.Views}} view{{PluralizeU64 .Photo.Views}}</span>
|
|
</span>
|
|
<small class="has-text-grey">Uploaded {{.Photo.CreatedAt.Format "Jan _2 2006 15:04:05"}}</small>
|
|
</div>
|
|
|
|
<!-- Show admin labels to admins -->
|
|
{{if .CurrentUser.HasAdminScope "social.moderator.photo"}}
|
|
{{if .Photo.AdminLabel}}
|
|
<div class="mt-2">
|
|
<i class="fa fa-peace has-text-danger mr-1"></i>
|
|
Admin Label: {{.Photo.AdminLabel}}
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
|
|
<!-- Quick mark photo as explicit -->
|
|
{{if and (not .Photo.Explicit) (ne .Photo.UserID .CurrentUser.ID) (not .Photo.HasAdminLabelNonExplicit)}}
|
|
<div class="mt-1">
|
|
<a href="#"
|
|
class="has-text-danger is-size-7 nonshy-mark-explicit"
|
|
data-photo-id="{{.Photo.ID}}" data-photo-url="{{PhotoURL .Photo.Filename}}">
|
|
<i class="fa fa-fire mr-1"></i>
|
|
Should this photo be marked Explicit?
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- Who likes this photo? -->
|
|
{{template "like-example" .}}
|
|
|
|
<!-- Like & Comments buttons -->
|
|
<div class="mt-4 mb-0 columns is-centered is-mobile is-gapless">
|
|
<div class="column is-narrow mr-2">
|
|
{{$Like := .LikeMap.Get .Photo.ID}}
|
|
<button type="button" class="button is-small nonshy-like-button"
|
|
data-table-name="photos" data-table-id="{{.Photo.ID}}"
|
|
title="Like">
|
|
<span class="icon{{if $Like.UserLikes}} has-text-danger{{end}}"><i class="fa fa-heart"></i></span>
|
|
<span class="nonshy-likes">
|
|
Like
|
|
{{if gt $Like.Count 0}}
|
|
({{$Like.Count}})
|
|
{{end}}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
<div class="column is-narrow">
|
|
<a href="/photo/view?id={{.Photo.ID}}#comments" class="button is-small">
|
|
<span class="icon"><i class="fa fa-comment"></i></span>
|
|
<span>{{$Comments}} Comment{{Pluralize64 $Comments}}</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Photo controls buttons (edit/delete/report) -->
|
|
<div class="my-2 columns is-centered is-mobile is-gapless">
|
|
<!-- Owned photo: have edit/delete buttons too -->
|
|
{{if or .IsOwnPhoto (.CurrentUser.HasAdminScope "social.moderator.photo")}}
|
|
<div class="column is-narrow">
|
|
<a href="/photo/edit?id={{.Photo.ID}}" class="button is-small">
|
|
<span class="icon"><i class="fa fa-edit"></i></span>
|
|
<span>Edit</span>
|
|
</a>
|
|
</div>
|
|
<div class="column is-narrow ml-2">
|
|
<a href="/photo/delete?id={{.Photo.ID}}" class="button is-small has-text-danger">
|
|
<span class="icon"><i class="fa fa-trash"></i></span>
|
|
<span>Delete</span>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- Report button except on your own pic -->
|
|
{{if not .IsOwnPhoto}}
|
|
<div class="column is-narrow mb-1">
|
|
<a href="/contact?intent=report&subject=report.photo&id={{.Photo.ID}}" class="button is-small has-text-danger">
|
|
<span class="icon"><i class="fa fa-flag"></i></span>
|
|
<span>Report</span>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
<!-- Admin links -->
|
|
{{if .CurrentUser.HasAdminScope "admin.changelog"}}
|
|
<div class="columns is-centered is-mobile is-gapless">
|
|
<div class="column is-narrow">
|
|
<a href="/admin/changelog?table_name=photos&table_id={{.Photo.ID}}" class="button is-small has-text-warning">
|
|
<span class="icon"><i class="fa fa-peace"></i></span>
|
|
<span>Change Log</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
</div><!-- /photo card -->
|
|
|
|
<!-- Comments Card -->
|
|
<div class="card" id="comments">
|
|
<header class="card-header has-background-success">
|
|
<p class="card-header-title has-text-light">
|
|
<span class="icon mr-2"><i class="fa fa-comment"></i></span>
|
|
<span>{{$Comments}} Comment{{Pluralize64 $Comments}}</span>
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content px-4">
|
|
<form action="/comments" method="POST">
|
|
{{InputCSRF}}
|
|
<input type="hidden" name="table_name" value="photos">
|
|
<input type="hidden" name="table_id" value="{{.Photo.ID}}">
|
|
<input type="hidden" name="next" value="{{.Request.URL.Path}}?id={{.Photo.ID}}">
|
|
|
|
<div class="field">
|
|
<label for="message">Add your comment</label>
|
|
<textarea class="textarea" cols="80" rows="4"
|
|
name="message" id="message"
|
|
placeholder="Add your comment"
|
|
required></textarea>
|
|
<p class="help">
|
|
<a href="/markdown" target="_blank">Markdown formatting</a> supported.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<p class="help">
|
|
<span class="has-text-warning">
|
|
<i class="fa fa-info-circle"></i>
|
|
<strong class="has-text-warning">Remember:</strong>
|
|
</span>
|
|
If you don't have anything <strong>nice</strong> to say, don't say anything at all!
|
|
It is <a href="/tos#hateful-content">strictly against the rules</a> to insult people
|
|
or be a bully.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="field has-text-centered">
|
|
<button type="submit" class="button is-link"
|
|
name="intent" value="preview">
|
|
Preview
|
|
</button>
|
|
|
|
<button type="submit" class="button is-success"
|
|
name="intent" value="submit">
|
|
Post Comment
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
<hr class="is-dark">
|
|
|
|
{{if not .IsOwnPhoto}}
|
|
<p class="mb-4">
|
|
<a href="/comments/subscription?table_name=photos&table_id={{.Photo.ID}}&next={{UrlEncode .Request.URL.String}}&subscribe={{if not .IsSubscribed}}true{{else}}false{{end}}">
|
|
<span class="icon"><i class="fa fa-bell{{if not .IsSubscribed}}-slash{{end}}"></i></span>
|
|
<span>
|
|
{{if .IsSubscribed}}
|
|
Disable notifications about this comment thread
|
|
{{else}}
|
|
Enable notifications about this comment thread
|
|
{{end}}
|
|
</span>
|
|
</a>
|
|
</p>
|
|
{{end}}
|
|
|
|
{{if eq $Comments 0}}
|
|
<p>
|
|
<em>There are no comments yet.</em>
|
|
</p>
|
|
{{else}}
|
|
{{range .Comments}}
|
|
<div class="box has-background-link-light has-text-dark" id="p{{.ID}}">
|
|
<div class="columns">
|
|
<div class="column is-2 has-text-centered">
|
|
<!-- User has no display name distinct from their username? -->
|
|
{{ $NoDisplayName := eq .User.NameOrUsername .User.Username }}
|
|
|
|
<div>
|
|
<a href="/u/{{.User.Username}}">
|
|
{{template "avatar-96x96" .User}}
|
|
</a>
|
|
</div>
|
|
<a href="/u/{{.User.Username}}">
|
|
{{- if $NoDisplayName}}<small class="is-size-7">@</small>{{end -}}
|
|
{{.User.NameOrUsername}}
|
|
</a>
|
|
|
|
<!-- Username if the display name wasn't identical -->
|
|
{{if not $NoDisplayName}}
|
|
<div class="is-size-7">
|
|
@{{.User.Username}}
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="column content">
|
|
{{ToMarkdown .Message}}
|
|
|
|
{{if .IsEdited}}
|
|
<div class="mt-4">
|
|
<em title="{{.UpdatedAt.Format "2006-01-02 15:04:05"}}">
|
|
<small>Edited {{SincePrettyCoarse .UpdatedAt}} ago</small>
|
|
</em>
|
|
</div>
|
|
{{end}}
|
|
|
|
<hr class="has-background-grey mb-2">
|
|
|
|
<div class="columns is-mobile is-multiline is-size-7 mb-0">
|
|
<div class="column is-narrow">
|
|
<span title="{{.CreatedAt.Format "2006-01-02 15:04:05"}}">
|
|
{{SincePrettyCoarse .CreatedAt}} ago
|
|
</span>
|
|
</div>
|
|
|
|
<div class="column is-narrow">
|
|
{{$Like := $Root.CommentLikeMap.Get .ID}}
|
|
<a href="#" class="has-text-dark nonshy-like-button"
|
|
data-table-name="comments" data-table-id="{{.ID}}"
|
|
title="Like">
|
|
<span class="icon{{if $Like.UserLikes}} has-text-danger{{end}}"><i class="fa fa-heart"></i></span>
|
|
<span class="nonshy-likes">
|
|
Like
|
|
{{if gt $Like.Count 0}}
|
|
({{$Like.Count}})
|
|
{{end}}
|
|
</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="column is-narrow">
|
|
<!-- Button to inspect the likes -->
|
|
<a href="#" class="has-text-dark"
|
|
onclick="ShowLikeModal('comments', {{.ID}}); return false">
|
|
<span class="icon"><i class="fa fa-eye"></i></span>
|
|
<span>Likes</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="column is-narrow">
|
|
<a href="/contact?intent=report&subject=report.comment&id={{.ID}}" class="has-text-dark">
|
|
<span class="icon"><i class="fa fa-flag"></i></span>
|
|
<span>Report</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="column is-narrow">
|
|
<a href="#"
|
|
class="has-text-dark nonshy-quote-button" data-quote-body="{{.Message}}" data-reply-to="{{.User.Username}}" data-comment-id="{{.ID}}">
|
|
<span class="icon"><i class="fa fa-quote-right"></i></span>
|
|
<span>Quote</span>
|
|
</a>
|
|
</div>
|
|
<div class="column is-narrow">
|
|
<a href="#"
|
|
class="has-text-dark nonshy-reply-button" data-reply-to="{{.User.Username}}" data-comment-id="{{.ID}}">
|
|
<span class="icon"><i class="fa fa-reply"></i></span>
|
|
<span>Reply</span>
|
|
</a>
|
|
</div>
|
|
|
|
{{if or $Root.CurrentUser.IsAdmin (eq $Root.CurrentUser.ID .User.ID)}}
|
|
<div class="column is-narrow">
|
|
<a href="/comments?table_name=photos&table_id={{$Root.Photo.ID}}&edit={{.ID}}&next={{UrlEncode $Root.Request.URL.Path "?id=" $Root.Photo.ID}}" class="has-text-dark">
|
|
<span class="icon"><i class="fa fa-edit"></i></span>
|
|
<span>Edit</span>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- The poster, the photo owner, and the admin can delete the comment -->
|
|
{{if or $Root.CurrentUser.IsAdmin (eq $Root.CurrentUser.ID .User.ID) $Root.IsOwnPhoto}}
|
|
<div class="column is-narrow">
|
|
<a href="/comments?table_name=photos&table_id={{$Root.Photo.ID}}&edit={{.ID}}&delete=true&next={{UrlEncode $Root.Request.URL.Path "?id=" $Root.Photo.ID}}" onclick="return confirm('Are you sure you want to delete this comment?')" class="has-text-dark">
|
|
<span class="icon"><i class="fa fa-trash"></i></span>
|
|
<span>Delete</span>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- Copy link to clipboard -->
|
|
<div class="column is-narrow">
|
|
<a href="/go/comment?id={{.ID}}" onclick="navigator.clipboard.writeText(this.href); window.location='#p{{.ID}}'; return false"
|
|
class="has-text-dark"
|
|
title="Copy link to clipboard">
|
|
<span class="icon"><i class="fa fa-paragraph"></i></span>
|
|
<span>Link</span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Admin: history -->
|
|
{{if $Root.CurrentUser.IsAdmin}}
|
|
<div class="column is-narrow">
|
|
<a href="/admin/changelog?table_name=comments&table_id={{.ID}}" class="has-text-warning">
|
|
<span class="icon"><i class="fa fa-clipboard-list"></i></span>
|
|
<span>Change log</span>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
{{if $Root.CurrentUser.IsAdmin}}
|
|
<div>
|
|
<span class="tag is-primary is-light">
|
|
<span class="icon"><i class="fa fa-database"></i></span>
|
|
<span>ID: {{.ID}}</span>
|
|
</span>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Enhance inline Quote and Reply buttons to activate the on-page comment textarea. -->
|
|
<script src="/static/js/inline-replies.js?build={{.BuildHash}}"></script>
|
|
|
|
<!-- Mark Explicit modal -->
|
|
{{template "mark-explicit-modal" .}}
|
|
{{end}}
|