add application (client) name to statuses (#497)

* add application (client) name to statuses

fixes another thing in #6

* add domain blocking (#496)

* add domain blocking

fixes another thing from #6

* show "domain blocking" on profile page

* fix stuff
This commit is contained in:
Nolan Lawson 2018-08-26 15:38:45 -07:00 committed by GitHub
parent 95665f6d74
commit 543536409b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 19 deletions

View file

@ -2,7 +2,7 @@
target="_blank" target="_blank"
{href} {href}
aria-label={ariaLabel} aria-label={ariaLabel}
class="{className || ''} {showIcon ? 'external-link-with-icon' : ''} {normalIconColor ? 'normal-icon-color' : ''}"> class={computedClass}>
<slot></slot>{#if showIcon} <slot></slot>{#if showIcon}
<svg class="external-link-svg"> <svg class="external-link-svg">
<use xlink:href="#fa-external-link" /> <use xlink:href="#fa-external-link" />
@ -24,12 +24,22 @@
} }
</style> </style>
<script> <script>
import { classname } from '../_utils/classname'
export default { export default {
data: () => ({ data: () => ({
className: void 0, className: void 0,
normalIconColor: false, normalIconColor: false,
ariaLabel: '', ariaLabel: '',
showIcon: false showIcon: false
}) }),
computed: {
computedClass: ({ className, showIcon, normalIconColor }) => (classname(
'external-link',
className,
showIcon && 'external-link-with-icon',
normalIconColor && 'normal-icon-color'
))
}
} }
</script> </script>

View file

@ -1,12 +1,26 @@
<div class="status-details"> <div class="status-details">
<ExternalLink className="status-absolute-date" <ExternalLink className="status-absolute-date"
href={originalStatus.url} href={originalStatus.url}
showIcon="true" showIcon={true}
ariaLabel="{formattedDate} (opens in new window)" ariaLabel="{formattedDate} (opens in new window)"
> >
<time datetime={createdAtDate} title={formattedDate}>{formattedDate}</time> <time datetime={createdAtDate} title={formattedDate}>{formattedDate}</time>
</ExternalLink> </ExternalLink>
<a class="status-favs-reblogs" {#if applicationWebsite}
<ExternalLink className="status-application"
href={applicationWebsite}
showIcon={false}
ariaLabel="{applicationName} (opens in new window)">
<span class="status-application-span">
{applicationName}
</span>
</ExternalLink>
{:else}
<span class="status-application status-application-span">
{applicationName}
</span>
{/if}
<a class="status-favs-reblogs status-reblogs"
href="/statuses/{originalStatusId}/reblogs" href="/statuses/{originalStatusId}/reblogs"
aria-label={reblogsLabel}> aria-label={reblogsLabel}>
<svg class="status-favs-reblogs-svg"> <svg class="status-favs-reblogs-svg">
@ -14,7 +28,7 @@
</svg> </svg>
<span>{numReblogs}</span> <span>{numReblogs}</span>
</a> </a>
<a class="status-favs-reblogs" <a class="status-favs-reblogs status-favs"
href="/statuses/{originalStatusId}/favorites" href="/statuses/{originalStatusId}/favorites"
aria-label={favoritesLabel}> aria-label={favoritesLabel}>
<svg class="status-favs-reblogs-svg"> <svg class="status-favs-reblogs-svg">
@ -27,7 +41,7 @@
.status-details { .status-details {
grid-area: details; grid-area: details;
display: grid; display: grid;
grid-template-columns: minmax(0, max-content) min-content min-content; grid-template-columns: minmax(0, max-content) min-content min-content min-content;
grid-gap: 20px; grid-gap: 20px;
align-items: center; align-items: center;
justify-content: left; justify-content: left;
@ -39,9 +53,33 @@
} }
:global(.status-absolute-date time) { :global(.status-absolute-date time) {
word-wrap: break-word;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
:global(.status-application) {
word-wrap: break-word; word-wrap: break-word;
overflow: hidden; overflow: hidden;
white-space: pre-wrap; white-space: pre-wrap;
font-size: 1.1em;
}
:global(.status-application, a.status-application, a.status-application:hover) {
color: var(--deemphasized-text-color);
}
:global(a.status-application) {
display: inline-flex;
align-items: center;
}
.status-application-span {
word-wrap: break-word;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
} }
.status-favs-reblogs { .status-favs-reblogs {
@ -78,6 +116,9 @@
.status-favs-reblogs { .status-favs-reblogs {
font-size: 1em; font-size: 1em;
} }
:global(.status-application) {
font-size: 1em;
}
.status-details { .status-details {
grid-gap: 5px; grid-gap: 5px;
justify-content: space-between; justify-content: space-between;
@ -88,21 +129,22 @@
</style> </style>
<script> <script>
import ExternalLink from '../ExternalLink.html' import ExternalLink from '../ExternalLink.html'
import { store } from '../../_store/store'
const formatter = new Intl.DateTimeFormat('en-US', { import { getDateFormatter, getShortDateFormatter } from '../../_utils/formatters'
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})
export default { export default {
store: () => store,
computed: { computed: {
application: ({ originalStatus }) => originalStatus.application,
applicationName: ({ application }) => ((application && application.name) || 'Web'),
applicationWebsite: ({ application }) => (application && application.website),
createdAtDate: ({ originalStatus }) => originalStatus.created_at, createdAtDate: ({ originalStatus }) => originalStatus.created_at,
numReblogs: ({ originalStatus }) => originalStatus.reblogs_count || 0, numReblogs: ({ originalStatus }) => originalStatus.reblogs_count || 0,
numFavs: ({ originalStatus }) => originalStatus.favourites_count || 0, numFavs: ({ originalStatus }) => originalStatus.favourites_count || 0,
formattedDate: ({ createdAtDate }) => formatter.format(new Date(createdAtDate)), formattedDate: ({ createdAtDate, $isMobileSize }) => {
let formatter = $isMobileSize ? getShortDateFormatter() : getDateFormatter()
return formatter.format(new Date(createdAtDate))
},
reblogsLabel: ({ numReblogs }) => { reblogsLabel: ({ numReblogs }) => {
// TODO: intl // TODO: intl
return numReblogs === 1 return numReblogs === 1

View file

@ -0,0 +1,29 @@
let dateFormatter
export function getDateFormatter () {
if (!dateFormatter) {
dateFormatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})
}
return dateFormatter
}
let shortDateFormatter
export function getShortDateFormatter () {
if (!shortDateFormatter) {
shortDateFormatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})
}
return shortDateFormatter
}

View file

@ -16,7 +16,7 @@ test('shows favorites', async t => {
.expect(getFavoritesCount()).eql(2) .expect(getFavoritesCount()).eql(2)
.expect(favoritesCountElement.getAttribute('aria-label')).eql('Favorited 2 times') .expect(favoritesCountElement.getAttribute('aria-label')).eql('Favorited 2 times')
.expect($('.icon-button[aria-label="Favorite"]').getAttribute('aria-pressed')).eql('true') .expect($('.icon-button[aria-label="Favorite"]').getAttribute('aria-pressed')).eql('true')
.click($('.status-favs-reblogs').nth(1)) .click(favoritesCountElement)
.expect(getUrl()).match(/\/statuses\/[^/]+\/favorites/) .expect(getUrl()).match(/\/statuses\/[^/]+\/favorites/)
.expect($('.search-result-account-name').nth(0).innerText).eql('foobar') .expect($('.search-result-account-name').nth(0).innerText).eql('foobar')
.expect($('.search-result-account-username').nth(0).innerText).eql('@foobar') .expect($('.search-result-account-username').nth(0).innerText).eql('@foobar')
@ -32,7 +32,7 @@ test('shows boosts', async t => {
.expect(getReblogsCount()).eql(1) .expect(getReblogsCount()).eql(1)
.expect(reblogsCountElement.getAttribute('aria-label')).eql('Boosted 1 time') .expect(reblogsCountElement.getAttribute('aria-label')).eql('Boosted 1 time')
.expect($('.icon-button[aria-label="Boost"]').getAttribute('aria-pressed')).eql('false') .expect($('.icon-button[aria-label="Boost"]').getAttribute('aria-pressed')).eql('false')
.click($('.status-favs-reblogs').nth(0)) .click(reblogsCountElement)
.expect(getUrl()).match(/\/statuses\/[^/]+\/reblogs/) .expect(getUrl()).match(/\/statuses\/[^/]+\/reblogs/)
.expect($('.search-result-account-name').nth(0).innerText).eql('admin') .expect($('.search-result-account-name').nth(0).innerText).eql('admin')
.expect($('.search-result-account-username').nth(0).innerText).eql('@admin') .expect($('.search-result-account-username').nth(0).innerText).eql('@admin')

View file

@ -44,11 +44,11 @@ export const displayNameInComposeBox = $('.compose-box-display-name')
export const generalSettingsButton = $('a[href="/settings/general"]') export const generalSettingsButton = $('a[href="/settings/general"]')
export const removeEmojiFromDisplayNamesInput = $('#choice-omit-emoji-in-display-names') export const removeEmojiFromDisplayNamesInput = $('#choice-omit-emoji-in-display-names')
export const favoritesCountElement = $('.status-favs-reblogs:nth-child(3)').addCustomDOMProperties({ export const favoritesCountElement = $('.status-favs').addCustomDOMProperties({
innerCount: el => parseInt(el.innerText, 10) innerCount: el => parseInt(el.innerText, 10)
}) })
export const reblogsCountElement = $('.status-favs-reblogs:nth-child(2)').addCustomDOMProperties({ export const reblogsCountElement = $('.status-reblogs').addCustomDOMProperties({
innerCount: el => parseInt(el.innerText, 10) innerCount: el => parseInt(el.innerText, 10)
}) })