forked from cybrespace/pinafore
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:
parent
95665f6d74
commit
543536409b
|
@ -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>
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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')
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue