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
					
				
					 5 changed files with 100 additions and 19 deletions
				
			
		| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
   target="_blank"
 | 
			
		||||
   {href}
 | 
			
		||||
   aria-label={ariaLabel}
 | 
			
		||||
   class="{className || ''} {showIcon ? 'external-link-with-icon' : ''} {normalIconColor ? 'normal-icon-color' : ''}">
 | 
			
		||||
   class={computedClass}>
 | 
			
		||||
  <slot></slot>{#if showIcon}
 | 
			
		||||
    <svg class="external-link-svg">
 | 
			
		||||
      <use xlink:href="#fa-external-link" />
 | 
			
		||||
| 
						 | 
				
			
			@ -24,12 +24,22 @@
 | 
			
		|||
  }
 | 
			
		||||
</style>
 | 
			
		||||
<script>
 | 
			
		||||
  import { classname } from '../_utils/classname'
 | 
			
		||||
 | 
			
		||||
  export default {
 | 
			
		||||
    data: () => ({
 | 
			
		||||
      className: void 0,
 | 
			
		||||
      normalIconColor: false,
 | 
			
		||||
      ariaLabel: '',
 | 
			
		||||
      showIcon: false
 | 
			
		||||
    })
 | 
			
		||||
    }),
 | 
			
		||||
    computed: {
 | 
			
		||||
      computedClass: ({ className, showIcon, normalIconColor }) => (classname(
 | 
			
		||||
        'external-link',
 | 
			
		||||
        className,
 | 
			
		||||
        showIcon && 'external-link-with-icon',
 | 
			
		||||
        normalIconColor && 'normal-icon-color'
 | 
			
		||||
      ))
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +1,26 @@
 | 
			
		|||
<div class="status-details">
 | 
			
		||||
  <ExternalLink className="status-absolute-date"
 | 
			
		||||
                href={originalStatus.url}
 | 
			
		||||
                showIcon="true"
 | 
			
		||||
                showIcon={true}
 | 
			
		||||
                ariaLabel="{formattedDate} (opens in new window)"
 | 
			
		||||
  >
 | 
			
		||||
    <time datetime={createdAtDate} title={formattedDate}>{formattedDate}</time>
 | 
			
		||||
  </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"
 | 
			
		||||
     aria-label={reblogsLabel}>
 | 
			
		||||
    <svg class="status-favs-reblogs-svg">
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +28,7 @@
 | 
			
		|||
    </svg>
 | 
			
		||||
    <span>{numReblogs}</span>
 | 
			
		||||
  </a>
 | 
			
		||||
  <a class="status-favs-reblogs"
 | 
			
		||||
  <a class="status-favs-reblogs status-favs"
 | 
			
		||||
     href="/statuses/{originalStatusId}/favorites"
 | 
			
		||||
     aria-label={favoritesLabel}>
 | 
			
		||||
    <svg class="status-favs-reblogs-svg">
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +41,7 @@
 | 
			
		|||
  .status-details {
 | 
			
		||||
    grid-area: details;
 | 
			
		||||
    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;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: left;
 | 
			
		||||
| 
						 | 
				
			
			@ -39,9 +53,33 @@
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  :global(.status-absolute-date time) {
 | 
			
		||||
    word-wrap: break-word;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  :global(.status-application) {
 | 
			
		||||
    word-wrap: break-word;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +116,9 @@
 | 
			
		|||
    .status-favs-reblogs {
 | 
			
		||||
      font-size: 1em;
 | 
			
		||||
    }
 | 
			
		||||
    :global(.status-application) {
 | 
			
		||||
      font-size: 1em;
 | 
			
		||||
    }
 | 
			
		||||
    .status-details {
 | 
			
		||||
      grid-gap: 5px;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
| 
						 | 
				
			
			@ -88,21 +129,22 @@
 | 
			
		|||
</style>
 | 
			
		||||
<script>
 | 
			
		||||
  import ExternalLink from '../ExternalLink.html'
 | 
			
		||||
 | 
			
		||||
  const formatter = new Intl.DateTimeFormat('en-US', {
 | 
			
		||||
    year: 'numeric',
 | 
			
		||||
    month: 'long',
 | 
			
		||||
    day: 'numeric',
 | 
			
		||||
    hour: '2-digit',
 | 
			
		||||
    minute: '2-digit'
 | 
			
		||||
  })
 | 
			
		||||
  import { store } from '../../_store/store'
 | 
			
		||||
  import { getDateFormatter, getShortDateFormatter } from '../../_utils/formatters'
 | 
			
		||||
 | 
			
		||||
  export default {
 | 
			
		||||
    store: () => store,
 | 
			
		||||
    computed: {
 | 
			
		||||
      application: ({ originalStatus }) => originalStatus.application,
 | 
			
		||||
      applicationName: ({ application }) => ((application && application.name) || 'Web'),
 | 
			
		||||
      applicationWebsite: ({ application }) => (application && application.website),
 | 
			
		||||
      createdAtDate: ({ originalStatus }) => originalStatus.created_at,
 | 
			
		||||
      numReblogs: ({ originalStatus }) => originalStatus.reblogs_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 }) => {
 | 
			
		||||
        // TODO: intl
 | 
			
		||||
        return numReblogs === 1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										29
									
								
								routes/_utils/formatters.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								routes/_utils/formatters.js
									
										
									
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ test('shows favorites', async t => {
 | 
			
		|||
    .expect(getFavoritesCount()).eql(2)
 | 
			
		||||
    .expect(favoritesCountElement.getAttribute('aria-label')).eql('Favorited 2 times')
 | 
			
		||||
    .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($('.search-result-account-name').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(reblogsCountElement.getAttribute('aria-label')).eql('Boosted 1 time')
 | 
			
		||||
    .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($('.search-result-account-name').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 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)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const reblogsCountElement = $('.status-favs-reblogs:nth-child(2)').addCustomDOMProperties({
 | 
			
		||||
export const reblogsCountElement = $('.status-reblogs').addCustomDOMProperties({
 | 
			
		||||
  innerCount: el => parseInt(el.innerText, 10)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue