Compare commits
	
		
			No commits in common. "12c5b732ae2c9303274c0fdb16b266dc073d22d9" and "9e6bc60abe6dfdaa54793d8d881be2d59d44f509" have entirely different histories.
		
	
	
		
			12c5b732ae
			...
			9e6bc60abe
		
	
		
					 26 changed files with 158 additions and 651 deletions
				
			
		| 
						 | 
					@ -61,7 +61,7 @@
 | 
				
			||||||
    "emoji-regex": "^8.0.0",
 | 
					    "emoji-regex": "^8.0.0",
 | 
				
			||||||
    "encoding": "^0.1.12",
 | 
					    "encoding": "^0.1.12",
 | 
				
			||||||
    "escape-html": "^1.0.3",
 | 
					    "escape-html": "^1.0.3",
 | 
				
			||||||
    "esm": "^3.2.25",
 | 
					    "esm": "^3.2.22",
 | 
				
			||||||
    "events-light": "^1.0.5",
 | 
					    "events-light": "^1.0.5",
 | 
				
			||||||
    "express": "^4.16.4",
 | 
					    "express": "^4.16.4",
 | 
				
			||||||
    "file-api": "^0.10.4",
 | 
					    "file-api": "^0.10.4",
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,7 @@
 | 
				
			||||||
    "requestidlecallback": "^0.3.0",
 | 
					    "requestidlecallback": "^0.3.0",
 | 
				
			||||||
    "rollup": "^1.11.3",
 | 
					    "rollup": "^1.11.3",
 | 
				
			||||||
    "rollup-plugin-replace": "^2.2.0",
 | 
					    "rollup-plugin-replace": "^2.2.0",
 | 
				
			||||||
    "rollup-plugin-terser": "^5.0.0",
 | 
					    "rollup-plugin-terser": "^4.0.4",
 | 
				
			||||||
    "sapper": "nolanlawson/sapper#for-pinafore-14",
 | 
					    "sapper": "nolanlawson/sapper#for-pinafore-14",
 | 
				
			||||||
    "stringz": "^1.0.0",
 | 
					    "stringz": "^1.0.0",
 | 
				
			||||||
    "svelte": "^2.16.1",
 | 
					    "svelte": "^2.16.1",
 | 
				
			||||||
| 
						 | 
					@ -103,7 +103,7 @@
 | 
				
			||||||
    "webpack-bundle-analyzer": "^3.3.2"
 | 
					    "webpack-bundle-analyzer": "^3.3.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "assert": "^2.0.0",
 | 
					    "assert": "^1.5.0",
 | 
				
			||||||
    "eslint-plugin-html": "^5.0.3",
 | 
					    "eslint-plugin-html": "^5.0.3",
 | 
				
			||||||
    "fake-indexeddb": "^2.1.0",
 | 
					    "fake-indexeddb": "^2.1.0",
 | 
				
			||||||
    "mocha": "^6.1.4",
 | 
					    "mocha": "^6.1.4",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <link id='theManifest' rel='manifest' href='/manifest.json' >
 | 
					  <link id='theManifest' rel='manifest' href='/manifest.json' >
 | 
				
			||||||
  <link id='theFavicon' rel='icon' type='image/png' href='/favicon.png' >
 | 
					  <link id='theFavicon' rel='icon' type='image/png' href='/favicon.png' >
 | 
				
			||||||
  <link rel="apple-touch-icon" href="/apple-icon.png" >
 | 
					  <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120.png" >
 | 
				
			||||||
 | 
					  <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180.png" >
 | 
				
			||||||
  <meta name="mobile-web-app-capable" content="yes" >
 | 
					  <meta name="mobile-web-app-capable" content="yes" >
 | 
				
			||||||
  <meta name="apple-mobile-web-app-title" content="Pinafore" >
 | 
					  <meta name="apple-mobile-web-app-title" content="Pinafore" >
 | 
				
			||||||
  <meta name="apple-mobile-web-app-status-bar-style" content="white" >
 | 
					  <meta name="apple-mobile-web-app-status-bar-style" content="white" >
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
// the build process and write it to checksum.js.
 | 
					// the build process and write it to checksum.js.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { testHasLocalStorageOnce } from '../routes/_utils/testStorage'
 | 
					import { testHasLocalStorageOnce } from '../routes/_utils/testStorage'
 | 
				
			||||||
import { INLINE_THEME, DEFAULT_THEME, switchToTheme } from '../routes/_utils/themeEngine'
 | 
					import { DEFAULT_LIGHT_THEME, DEFAULT_THEME, switchToTheme } from '../routes/_utils/themeEngine'
 | 
				
			||||||
import { basename } from '../routes/_api/utils'
 | 
					import { basename } from '../routes/_api/utils'
 | 
				
			||||||
import { onUserIsLoggedOut } from '../routes/_actions/onUserIsLoggedOut'
 | 
					import { onUserIsLoggedOut } from '../routes/_actions/onUserIsLoggedOut'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ let theme = (currentInstance &&
 | 
				
			||||||
  localStorage.store_instanceThemes &&
 | 
					  localStorage.store_instanceThemes &&
 | 
				
			||||||
  safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)]) ||
 | 
					  safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)]) ||
 | 
				
			||||||
  DEFAULT_THEME
 | 
					  DEFAULT_THEME
 | 
				
			||||||
if (theme !== INLINE_THEME) {
 | 
					if (theme !== DEFAULT_LIGHT_THEME) {
 | 
				
			||||||
  // switch theme ASAP to minimize flash of default theme
 | 
					  // switch theme ASAP to minimize flash of default theme
 | 
				
			||||||
  switchToTheme(theme)
 | 
					  switchToTheme(theme)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,48 +0,0 @@
 | 
				
			||||||
<div class="generic-instance-settings">
 | 
					 | 
				
			||||||
  <form aria-label={label} ref:form>
 | 
					 | 
				
			||||||
    {#each options as option, i (option.key) }
 | 
					 | 
				
			||||||
      {#if i > 0}
 | 
					 | 
				
			||||||
        <br>
 | 
					 | 
				
			||||||
      {/if}
 | 
					 | 
				
			||||||
      <input type="checkbox"
 | 
					 | 
				
			||||||
             id="instance-option-{option.key}"
 | 
					 | 
				
			||||||
             name="{option.key}"
 | 
					 | 
				
			||||||
             on:change="onChange(event)"
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
      <label for="instance-option-{option.key}">
 | 
					 | 
				
			||||||
        {option.label}
 | 
					 | 
				
			||||||
      </label>
 | 
					 | 
				
			||||||
    {/each}
 | 
					 | 
				
			||||||
  </form>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
  .generic-instance-settings {
 | 
					 | 
				
			||||||
    background: var(--form-bg);
 | 
					 | 
				
			||||||
    border: 1px solid var(--main-border);
 | 
					 | 
				
			||||||
    border-radius: 4px;
 | 
					 | 
				
			||||||
    display: block;
 | 
					 | 
				
			||||||
    padding: 20px;
 | 
					 | 
				
			||||||
    line-height: 2em;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
  import { store } from '../../../_store/store'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  export default {
 | 
					 | 
				
			||||||
    oncreate () {
 | 
					 | 
				
			||||||
      let { instanceName, options } = this.get()
 | 
					 | 
				
			||||||
      let { form } = this.refs
 | 
					 | 
				
			||||||
      for (let { key, defaultValue } of options) {
 | 
					 | 
				
			||||||
        form.elements[key].checked = this.store.getInstanceSetting(instanceName, key, defaultValue)
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
      onChange (event) {
 | 
					 | 
				
			||||||
        let { instanceName } = this.get()
 | 
					 | 
				
			||||||
        let { target } = event
 | 
					 | 
				
			||||||
        this.store.setInstanceSetting(instanceName, target.name, target.checked)
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    store: () => store
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,29 +0,0 @@
 | 
				
			||||||
<GenericInstanceSettings
 | 
					 | 
				
			||||||
  {instanceName}
 | 
					 | 
				
			||||||
  {options}
 | 
					 | 
				
			||||||
  label="Home timeline filter settings"
 | 
					 | 
				
			||||||
/>
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
  import GenericInstanceSettings from './GenericInstanceSettings.html'
 | 
					 | 
				
			||||||
  import { HOME_REBLOGS, HOME_REPLIES } from '../../../_static/instanceSettings'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  export default {
 | 
					 | 
				
			||||||
    data: () => ({
 | 
					 | 
				
			||||||
      options: [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: HOME_REBLOGS,
 | 
					 | 
				
			||||||
          label: 'Show boosts',
 | 
					 | 
				
			||||||
          defaultValue: true
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: HOME_REPLIES,
 | 
					 | 
				
			||||||
          label: 'Show replies',
 | 
					 | 
				
			||||||
          defaultValue: true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    components: {
 | 
					 | 
				
			||||||
      GenericInstanceSettings
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,50 +0,0 @@
 | 
				
			||||||
<GenericInstanceSettings
 | 
					 | 
				
			||||||
  {instanceName}
 | 
					 | 
				
			||||||
  {options}
 | 
					 | 
				
			||||||
  label="Notification filter settings"
 | 
					 | 
				
			||||||
/>
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
  import GenericInstanceSettings from './GenericInstanceSettings.html'
 | 
					 | 
				
			||||||
  import {
 | 
					 | 
				
			||||||
    NOTIFICATION_REBLOGS,
 | 
					 | 
				
			||||||
    NOTIFICATION_FAVORITES,
 | 
					 | 
				
			||||||
    NOTIFICATION_FOLLOWS,
 | 
					 | 
				
			||||||
    NOTIFICATION_MENTIONS,
 | 
					 | 
				
			||||||
    NOTIFICATION_POLLS
 | 
					 | 
				
			||||||
  } from '../../../_static/instanceSettings'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  export default {
 | 
					 | 
				
			||||||
    data: () => ({
 | 
					 | 
				
			||||||
      options: [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: NOTIFICATION_FOLLOWS,
 | 
					 | 
				
			||||||
          label: 'New followers',
 | 
					 | 
				
			||||||
          defaultValue: true
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: NOTIFICATION_FAVORITES,
 | 
					 | 
				
			||||||
          label: 'Favorites',
 | 
					 | 
				
			||||||
          defaultValue: true
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: NOTIFICATION_REBLOGS,
 | 
					 | 
				
			||||||
          label: 'Boosts',
 | 
					 | 
				
			||||||
          defaultValue: true
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: NOTIFICATION_MENTIONS,
 | 
					 | 
				
			||||||
          label: 'Mentions',
 | 
					 | 
				
			||||||
          defaultValue: true
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: NOTIFICATION_POLLS,
 | 
					 | 
				
			||||||
          label: 'Poll results',
 | 
					 | 
				
			||||||
          defaultValue: true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    components: {
 | 
					 | 
				
			||||||
      GenericInstanceSettings
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -4,21 +4,18 @@
 | 
				
			||||||
  {:elseif $notificationPermission === "denied"}
 | 
					  {:elseif $notificationPermission === "denied"}
 | 
				
			||||||
  <p role="alert">You have denied permission to show notifications.</p>
 | 
					  <p role="alert">You have denied permission to show notifications.</p>
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
  <form id="push-notification-settings"
 | 
					  <form id="push-notification-settings" disabled="{!pushNotificationsSupport}" ref:pushNotificationsForm aria-label="Push notification settings">
 | 
				
			||||||
        disabled="{!pushNotificationsSupport}"
 | 
					    <input type="checkbox" id="push-notifications-follow" name="follow" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
 | 
				
			||||||
        ref:form
 | 
					    <label for="push-notifications-follow">New followers</label>
 | 
				
			||||||
        aria-label="Push notification settings">
 | 
					    <br>
 | 
				
			||||||
    {#each options as option, i (option.key)}
 | 
					    <input type="checkbox" id="push-notifications-favourite" name="favourite" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
 | 
				
			||||||
      {#if i > 0}
 | 
					    <label for="push-notifications-favourite">Favourites</label>
 | 
				
			||||||
        <br>
 | 
					    <br>
 | 
				
			||||||
      {/if}
 | 
					    <input type="checkbox" id="push-notifications-reblog" name="reblog" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
 | 
				
			||||||
      <input type="checkbox"
 | 
					    <label for="push-notifications-reblog">Boosts</label>
 | 
				
			||||||
             id="push-notifications-{option.key}"
 | 
					    <br>
 | 
				
			||||||
             name="{option.key}"
 | 
					    <input type="checkbox" id="push-notifications-mention" name="mention" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
 | 
				
			||||||
             disabled="{!pushNotificationsSupport}"
 | 
					    <label for="push-notifications-mention">Mentions</label>
 | 
				
			||||||
             on:change="onPushSettingsChange(event)">
 | 
					 | 
				
			||||||
      <label for="push-notifications-{option.key}">{option.label}</label>
 | 
					 | 
				
			||||||
    {/each}
 | 
					 | 
				
			||||||
  </form>
 | 
					  </form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
| 
						 | 
					@ -30,11 +27,11 @@
 | 
				
			||||||
    padding: 20px;
 | 
					    padding: 20px;
 | 
				
			||||||
    line-height: 2em;
 | 
					    line-height: 2em;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  form[disabled="true"] {
 | 
					  .push-notifications form[disabled="true"] {
 | 
				
			||||||
    opacity: 0.5;
 | 
					    opacity: 0.5;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  p {
 | 
					  .push-notifications p {
 | 
				
			||||||
    margin: 0 0 10px 0;
 | 
					    margin: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
| 
						 | 
					@ -43,56 +40,33 @@
 | 
				
			||||||
  import { logOutOfInstance } from '../../../_actions/instances'
 | 
					  import { logOutOfInstance } from '../../../_actions/instances'
 | 
				
			||||||
  import { updatePushSubscriptionForInstance, updateAlerts } from '../../../_actions/pushSubscription'
 | 
					  import { updatePushSubscriptionForInstance, updateAlerts } from '../../../_actions/pushSubscription'
 | 
				
			||||||
  import { toast } from '../../toast/toast'
 | 
					  import { toast } from '../../toast/toast'
 | 
				
			||||||
  import { get } from '../../../_utils/lodash-lite'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export default {
 | 
					  export default {
 | 
				
			||||||
    async oncreate () {
 | 
					    async oncreate () {
 | 
				
			||||||
      let { instanceName, options } = this.get()
 | 
					      let { instanceName } = this.get()
 | 
				
			||||||
      await updatePushSubscriptionForInstance(instanceName)
 | 
					      await updatePushSubscriptionForInstance(instanceName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const { form } = this.refs
 | 
					      const form = this.refs.pushNotificationsForm
 | 
				
			||||||
      const { pushSubscription } = this.store.get()
 | 
					      const { pushSubscription } = this.store.get()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (let { key } of options) {
 | 
					      form.elements.follow.checked = pushSubscription && pushSubscription.alerts && pushSubscription.alerts.follow
 | 
				
			||||||
        form.elements[key].checked = get(pushSubscription, ['alerts', key])
 | 
					      form.elements.favourite.checked = pushSubscription && pushSubscription.alerts && pushSubscription.alerts.favourite
 | 
				
			||||||
      }
 | 
					      form.elements.reblog.checked = pushSubscription && pushSubscription.alerts && pushSubscription.alerts.reblog
 | 
				
			||||||
 | 
					      form.elements.mention.checked = pushSubscription && pushSubscription.alerts && pushSubscription.alerts.mention
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    store: () => store,
 | 
					    store: () => store,
 | 
				
			||||||
    data: () => ({
 | 
					 | 
				
			||||||
      options: [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: 'follow',
 | 
					 | 
				
			||||||
          label: 'New Followers'
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: 'favourite',
 | 
					 | 
				
			||||||
          label: 'Favorites'
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: 'reblog',
 | 
					 | 
				
			||||||
          label: 'Boosts'
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: 'mention',
 | 
					 | 
				
			||||||
          label: 'Mentions'
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          key: 'poll',
 | 
					 | 
				
			||||||
          label: 'Poll results'
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    computed: {
 | 
					    computed: {
 | 
				
			||||||
      pushNotificationsSupport: ({ $pushNotificationsSupport }) => $pushNotificationsSupport
 | 
					      pushNotificationsSupport: ({ $pushNotificationsSupport }) => $pushNotificationsSupport
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    methods: {
 | 
					    methods: {
 | 
				
			||||||
      async onPushSettingsChange (e) {
 | 
					      async onPushSettingsChange (e) {
 | 
				
			||||||
        const { instanceName, options } = this.get()
 | 
					        const { instanceName } = this.get()
 | 
				
			||||||
        const { form } = this.refs
 | 
					        const form = this.refs.pushNotificationsForm
 | 
				
			||||||
        const alerts = {}
 | 
					        const alerts = {
 | 
				
			||||||
 | 
					          follow: form.elements.follow.checked,
 | 
				
			||||||
        for (let { key } of options) {
 | 
					          favourite: form.elements.favourite.checked,
 | 
				
			||||||
          alerts[key] = form.elements[key].checked
 | 
					          reblog: form.elements.reblog.checked,
 | 
				
			||||||
 | 
					          mention: form.elements.mention.checked
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,9 +31,6 @@
 | 
				
			||||||
  {#if showMedia }
 | 
					  {#if showMedia }
 | 
				
			||||||
    <StatusMediaAttachments {...params} on:recalculateHeight />
 | 
					    <StatusMediaAttachments {...params} on:recalculateHeight />
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
  {#if showPoll}
 | 
					 | 
				
			||||||
    <StatusPoll {...params} />
 | 
					 | 
				
			||||||
  {/if}
 | 
					 | 
				
			||||||
  {#if isStatusInOwnThread}
 | 
					  {#if isStatusInOwnThread}
 | 
				
			||||||
    <StatusDetails {...params} />
 | 
					    <StatusDetails {...params} />
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
| 
						 | 
					@ -61,7 +58,6 @@
 | 
				
			||||||
        "sidebar content      content       content"
 | 
					        "sidebar content      content       content"
 | 
				
			||||||
        "sidebar card         card          card"
 | 
					        "sidebar card         card          card"
 | 
				
			||||||
        "sidebar media-grp    media-grp     media-grp"
 | 
					        "sidebar media-grp    media-grp     media-grp"
 | 
				
			||||||
        "sidebar poll         poll          poll"
 | 
					 | 
				
			||||||
        "media   media        media         media"
 | 
					        "media   media        media         media"
 | 
				
			||||||
        "....... toolbar      toolbar       toolbar"
 | 
					        "....... toolbar      toolbar       toolbar"
 | 
				
			||||||
        "compose compose      compose       compose";
 | 
					        "compose compose      compose       compose";
 | 
				
			||||||
| 
						 | 
					@ -96,7 +92,6 @@
 | 
				
			||||||
      "card        card"
 | 
					      "card        card"
 | 
				
			||||||
      "media-grp   media-grp"
 | 
					      "media-grp   media-grp"
 | 
				
			||||||
      "media       media"
 | 
					      "media       media"
 | 
				
			||||||
      "poll        poll"
 | 
					 | 
				
			||||||
      "details     details"
 | 
					      "details     details"
 | 
				
			||||||
      "toolbar     toolbar"
 | 
					      "toolbar     toolbar"
 | 
				
			||||||
      "compose     compose";
 | 
					      "compose     compose";
 | 
				
			||||||
| 
						 | 
					@ -124,7 +119,6 @@
 | 
				
			||||||
  import StatusSpoiler from './StatusSpoiler.html'
 | 
					  import StatusSpoiler from './StatusSpoiler.html'
 | 
				
			||||||
  import StatusComposeBox from './StatusComposeBox.html'
 | 
					  import StatusComposeBox from './StatusComposeBox.html'
 | 
				
			||||||
  import StatusMentions from './StatusMentions.html'
 | 
					  import StatusMentions from './StatusMentions.html'
 | 
				
			||||||
  import StatusPoll from './StatusPoll.html'
 | 
					 | 
				
			||||||
  import Shortcut from '../shortcut/Shortcut.html'
 | 
					  import Shortcut from '../shortcut/Shortcut.html'
 | 
				
			||||||
  import { store } from '../../_store/store'
 | 
					  import { store } from '../../_store/store'
 | 
				
			||||||
  import { goto } from '../../../../__sapper__/client'
 | 
					  import { goto } from '../../../../__sapper__/client'
 | 
				
			||||||
| 
						 | 
					@ -176,7 +170,6 @@
 | 
				
			||||||
      StatusMediaAttachments,
 | 
					      StatusMediaAttachments,
 | 
				
			||||||
      StatusContent,
 | 
					      StatusContent,
 | 
				
			||||||
      StatusCard,
 | 
					      StatusCard,
 | 
				
			||||||
      StatusPoll,
 | 
					 | 
				
			||||||
      StatusSpoiler,
 | 
					      StatusSpoiler,
 | 
				
			||||||
      StatusComposeBox,
 | 
					      StatusComposeBox,
 | 
				
			||||||
      StatusMentions,
 | 
					      StatusMentions,
 | 
				
			||||||
| 
						 | 
					@ -268,9 +261,6 @@
 | 
				
			||||||
        originalStatus.card &&
 | 
					        originalStatus.card &&
 | 
				
			||||||
        originalStatus.card.title
 | 
					        originalStatus.card.title
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      showPoll: ({ originalStatus, isStatusInNotification }) => (
 | 
					 | 
				
			||||||
        !isStatusInNotification && originalStatus.poll
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      showMedia: ({ originalStatus, isStatusInNotification }) => (
 | 
					      showMedia: ({ originalStatus, isStatusInNotification }) => (
 | 
				
			||||||
        !isStatusInNotification &&
 | 
					        !isStatusInNotification &&
 | 
				
			||||||
        originalStatus.media_attachments &&
 | 
					        originalStatus.media_attachments &&
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,61 +0,0 @@
 | 
				
			||||||
<div class="poll" >
 | 
					 | 
				
			||||||
  <ul class="options" aria-label="Poll results">
 | 
					 | 
				
			||||||
    {#each options as option}
 | 
					 | 
				
			||||||
      <li class="option">
 | 
					 | 
				
			||||||
        <div class="option-text">{option.title} ({option.share}%)</div>
 | 
					 | 
				
			||||||
        <svg aria-hidden="true">
 | 
					 | 
				
			||||||
          <line x1="0" y1="0" x2="{option.share}%" y2="0" />
 | 
					 | 
				
			||||||
        </svg>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
    {/each}
 | 
					 | 
				
			||||||
  </ul>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
  .poll {
 | 
					 | 
				
			||||||
    grid-area: poll;
 | 
					 | 
				
			||||||
    margin: 10px 10px 10px 5px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ul.options {
 | 
					 | 
				
			||||||
    list-style: none;
 | 
					 | 
				
			||||||
    margin: 0;
 | 
					 | 
				
			||||||
    padding: 0;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  li.option {
 | 
					 | 
				
			||||||
    margin: 0 0 10px 0;
 | 
					 | 
				
			||||||
    padding: 0;
 | 
					 | 
				
			||||||
    display: flex;
 | 
					 | 
				
			||||||
    flex-direction: column;
 | 
					 | 
				
			||||||
    stroke: var(--svg-fill);
 | 
					 | 
				
			||||||
    stroke-width: 5px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  li.option:last-child {
 | 
					 | 
				
			||||||
    margin: 0;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  .option-text {
 | 
					 | 
				
			||||||
    word-wrap: break-word;
 | 
					 | 
				
			||||||
    white-space: pre-wrap;
 | 
					 | 
				
			||||||
    font-size: 1.1em;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  svg {
 | 
					 | 
				
			||||||
    height: 2px;
 | 
					 | 
				
			||||||
    width: 100%;
 | 
					 | 
				
			||||||
    margin-top: 5px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
  export default {
 | 
					 | 
				
			||||||
    computed: {
 | 
					 | 
				
			||||||
      poll: ({ originalStatus }) => originalStatus.poll,
 | 
					 | 
				
			||||||
      options: ({ poll }) => poll.options.map(({ title, votes_count: votesCount }) => ({
 | 
					 | 
				
			||||||
        title,
 | 
					 | 
				
			||||||
        share: poll.votes_count ? Math.round(votesCount / poll.votes_count * 100) : 0
 | 
					 | 
				
			||||||
      }))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -59,22 +59,6 @@
 | 
				
			||||||
  import { observe } from 'svelte-extras'
 | 
					  import { observe } from 'svelte-extras'
 | 
				
			||||||
  import { createMakeProps } from '../../_actions/createMakeProps'
 | 
					  import { createMakeProps } from '../../_actions/createMakeProps'
 | 
				
			||||||
  import { showMoreAndScrollToTop } from '../../_actions/showMoreAndScrollToTop'
 | 
					  import { showMoreAndScrollToTop } from '../../_actions/showMoreAndScrollToTop'
 | 
				
			||||||
  import { get } from '../../_utils/lodash-lite'
 | 
					 | 
				
			||||||
  import {
 | 
					 | 
				
			||||||
    HOME_REBLOGS,
 | 
					 | 
				
			||||||
    HOME_REPLIES,
 | 
					 | 
				
			||||||
    NOTIFICATION_REBLOGS,
 | 
					 | 
				
			||||||
    NOTIFICATION_FOLLOWS,
 | 
					 | 
				
			||||||
    NOTIFICATION_FAVORITES,
 | 
					 | 
				
			||||||
    NOTIFICATION_POLLS,
 | 
					 | 
				
			||||||
    NOTIFICATION_MENTIONS,
 | 
					 | 
				
			||||||
    FILTER_FAVORITE,
 | 
					 | 
				
			||||||
    FILTER_FOLLOW,
 | 
					 | 
				
			||||||
    FILTER_MENTION,
 | 
					 | 
				
			||||||
    FILTER_POLL,
 | 
					 | 
				
			||||||
    FILTER_REBLOG,
 | 
					 | 
				
			||||||
    FILTER_REPLY
 | 
					 | 
				
			||||||
  } from '../../_static/instanceSettings'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export default {
 | 
					  export default {
 | 
				
			||||||
    oncreate () {
 | 
					    oncreate () {
 | 
				
			||||||
| 
						 | 
					@ -143,56 +127,9 @@
 | 
				
			||||||
        timelineValue !== $firstTimelineItemId &&
 | 
					        timelineValue !== $firstTimelineItemId &&
 | 
				
			||||||
        timelineValue
 | 
					        timelineValue
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      currentInstanceSettings: ({ $currentInstance, $instanceSettings }) => (
 | 
					      itemIds: ({ $timelineItemSummaries }) => (
 | 
				
			||||||
        $instanceSettings[$currentInstance] || {}
 | 
					        // TODO: filter
 | 
				
			||||||
      ),
 | 
					        $timelineItemSummaries && $timelineItemSummaries.map(_ => _.id)
 | 
				
			||||||
      timelineFilters: ({ currentInstanceSettings, timeline }) => {
 | 
					 | 
				
			||||||
        if (timeline === 'home') {
 | 
					 | 
				
			||||||
          return {
 | 
					 | 
				
			||||||
            [FILTER_REBLOG]: get(currentInstanceSettings, [HOME_REBLOGS], true),
 | 
					 | 
				
			||||||
            [FILTER_REPLY]: get(currentInstanceSettings, [HOME_REPLIES], true)
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        } else if (timeline === 'notifications') {
 | 
					 | 
				
			||||||
          return {
 | 
					 | 
				
			||||||
            [FILTER_REBLOG]: get(currentInstanceSettings, [NOTIFICATION_REBLOGS], true),
 | 
					 | 
				
			||||||
            [FILTER_FOLLOW]: get(currentInstanceSettings, [NOTIFICATION_FOLLOWS], true),
 | 
					 | 
				
			||||||
            [FILTER_FAVORITE]: get(currentInstanceSettings, [NOTIFICATION_FAVORITES], true),
 | 
					 | 
				
			||||||
            [FILTER_MENTION]: get(currentInstanceSettings, [NOTIFICATION_MENTIONS], true),
 | 
					 | 
				
			||||||
            [FILTER_POLL]: get(currentInstanceSettings, [NOTIFICATION_POLLS], true)
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      showReblogs: ({ timelineFilters }) => get(timelineFilters, [FILTER_REBLOG], true),
 | 
					 | 
				
			||||||
      showReplies: ({ timelineFilters }) => get(timelineFilters, [FILTER_REPLY], true),
 | 
					 | 
				
			||||||
      showFollows: ({ timelineFilters }) => get(timelineFilters, [FILTER_FOLLOW], true),
 | 
					 | 
				
			||||||
      showMentions: ({ timelineFilters }) => get(timelineFilters, [FILTER_MENTION], true),
 | 
					 | 
				
			||||||
      showPolls: ({ timelineFilters }) => get(timelineFilters, [FILTER_POLL], true),
 | 
					 | 
				
			||||||
      showFavs: ({ timelineFilters }) => get(timelineFilters, [FILTER_FAVORITE], true),
 | 
					 | 
				
			||||||
      itemIds: ({
 | 
					 | 
				
			||||||
        $timelineItemSummaries, showReblogs, showReplies, showFollows, showMentions,
 | 
					 | 
				
			||||||
        showPolls, showFavs
 | 
					 | 
				
			||||||
      }) => (
 | 
					 | 
				
			||||||
        $timelineItemSummaries && $timelineItemSummaries.filter(item => {
 | 
					 | 
				
			||||||
          switch (item.type) {
 | 
					 | 
				
			||||||
            case 'poll':
 | 
					 | 
				
			||||||
              return showPolls
 | 
					 | 
				
			||||||
            case 'favourite':
 | 
					 | 
				
			||||||
              return showFavs
 | 
					 | 
				
			||||||
            case 'reblog':
 | 
					 | 
				
			||||||
              return showReblogs
 | 
					 | 
				
			||||||
            case 'mention':
 | 
					 | 
				
			||||||
              return showMentions
 | 
					 | 
				
			||||||
            case 'follow':
 | 
					 | 
				
			||||||
              return showFollows
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          if (item.reblogId) {
 | 
					 | 
				
			||||||
            return showReblogs
 | 
					 | 
				
			||||||
          } else if (item.replyId) {
 | 
					 | 
				
			||||||
            return showReplies
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            return true
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }).map(_ => _.id)
 | 
					 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      itemIdsToAdd: ({ $timelineItemSummariesToAdd }) => (
 | 
					      itemIdsToAdd: ({ $timelineItemSummariesToAdd }) => (
 | 
				
			||||||
        // TODO: filter
 | 
					        // TODO: filter
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,15 +3,15 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <h2>Media</h2>
 | 
					  <h2>Media</h2>
 | 
				
			||||||
  <form class="ui-settings">
 | 
					  <form class="ui-settings">
 | 
				
			||||||
    <div class="setting-group">
 | 
					 | 
				
			||||||
      <input type="checkbox" id="choice-never-mark-media-sensitive"
 | 
					 | 
				
			||||||
             bind:checked="$neverMarkMediaAsSensitive" on:change="onChange(event)">
 | 
					 | 
				
			||||||
      <label for="choice-never-mark-media-sensitive">Show sensitive media by default</label>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="setting-group">
 | 
					    <div class="setting-group">
 | 
				
			||||||
      <input type="checkbox" id="choice-mark-media-sensitive"
 | 
					      <input type="checkbox" id="choice-mark-media-sensitive"
 | 
				
			||||||
             bind:checked="$markMediaAsSensitive" on:change="onChange(event)">
 | 
					             bind:checked="$markMediaAsSensitive" on:change="onChange(event)">
 | 
				
			||||||
      <label for="choice-mark-media-sensitive">Hide all media by default</label>
 | 
					      <label for="choice-mark-media-sensitive">Always mark media as sensitive</label>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="setting-group">
 | 
				
			||||||
 | 
					      <input type="checkbox" id="choice-never-mark-media-sensitive"
 | 
				
			||||||
 | 
					             bind:checked="$neverMarkMediaAsSensitive" on:change="onChange(event)">
 | 
				
			||||||
 | 
					      <label for="choice-never-mark-media-sensitive">Never mark media as sensitive</label>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="setting-group">
 | 
					    <div class="setting-group">
 | 
				
			||||||
      <input type="checkbox" id="choice-large-inline-media"
 | 
					      <input type="checkbox" id="choice-large-inline-media"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,13 +4,9 @@
 | 
				
			||||||
  {#if verifyCredentials}
 | 
					  {#if verifyCredentials}
 | 
				
			||||||
    <h2>Logged in as:</h2>
 | 
					    <h2>Logged in as:</h2>
 | 
				
			||||||
    <InstanceUserProfile {verifyCredentials} />
 | 
					    <InstanceUserProfile {verifyCredentials} />
 | 
				
			||||||
    <h2>Home timeline filters</h2>
 | 
					    <h2>Push notifications:</h2>
 | 
				
			||||||
    <HomeTimelineFilterSettings {instanceName} />
 | 
					 | 
				
			||||||
    <h2>Notification filters</h2>
 | 
					 | 
				
			||||||
    <NotificationFilterSettings {instanceName} />
 | 
					 | 
				
			||||||
    <h2>Push notifications</h2>
 | 
					 | 
				
			||||||
    <PushNotificationSettings {instanceName} />
 | 
					    <PushNotificationSettings {instanceName} />
 | 
				
			||||||
    <h2>Theme</h2>
 | 
					    <h2>Theme:</h2>
 | 
				
			||||||
    <ThemeSettings {instanceName} />
 | 
					    <ThemeSettings {instanceName} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <InstanceActions {instanceName} />
 | 
					    <InstanceActions {instanceName} />
 | 
				
			||||||
| 
						 | 
					@ -27,8 +23,6 @@
 | 
				
			||||||
  import { store } from '../../../_store/store'
 | 
					  import { store } from '../../../_store/store'
 | 
				
			||||||
  import SettingsLayout from '../../../_components/settings/SettingsLayout.html'
 | 
					  import SettingsLayout from '../../../_components/settings/SettingsLayout.html'
 | 
				
			||||||
  import InstanceUserProfile from '../../../_components/settings/instance/InstanceUserProfile.html'
 | 
					  import InstanceUserProfile from '../../../_components/settings/instance/InstanceUserProfile.html'
 | 
				
			||||||
  import HomeTimelineFilterSettings from '../../../_components/settings/instance/HomeTimelineFilterSettings.html'
 | 
					 | 
				
			||||||
  import NotificationFilterSettings from '../../../_components/settings/instance/NotificationFilterSettings.html'
 | 
					 | 
				
			||||||
  import PushNotificationSettings from '../../../_components/settings/instance/PushNotificationSettings.html'
 | 
					  import PushNotificationSettings from '../../../_components/settings/instance/PushNotificationSettings.html'
 | 
				
			||||||
  import ThemeSettings from '../../../_components/settings/instance/ThemeSettings.html'
 | 
					  import ThemeSettings from '../../../_components/settings/instance/ThemeSettings.html'
 | 
				
			||||||
  import InstanceActions from '../../../_components/settings/instance/InstanceActions.html'
 | 
					  import InstanceActions from '../../../_components/settings/instance/InstanceActions.html'
 | 
				
			||||||
| 
						 | 
					@ -49,9 +43,7 @@
 | 
				
			||||||
      InstanceUserProfile,
 | 
					      InstanceUserProfile,
 | 
				
			||||||
      PushNotificationSettings,
 | 
					      PushNotificationSettings,
 | 
				
			||||||
      ThemeSettings,
 | 
					      ThemeSettings,
 | 
				
			||||||
      InstanceActions,
 | 
					      InstanceActions
 | 
				
			||||||
      HomeTimelineFilterSettings,
 | 
					 | 
				
			||||||
      NotificationFilterSettings
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -1,15 +0,0 @@
 | 
				
			||||||
export const HOME_REBLOGS = 'homeReblogs'
 | 
					 | 
				
			||||||
export const HOME_REPLIES = 'homeReplies'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const NOTIFICATION_REBLOGS = 'notificationReblogs'
 | 
					 | 
				
			||||||
export const NOTIFICATION_FAVORITES = 'notificationFavs'
 | 
					 | 
				
			||||||
export const NOTIFICATION_FOLLOWS = 'notificationFollows'
 | 
					 | 
				
			||||||
export const NOTIFICATION_MENTIONS = 'notificationMentions'
 | 
					 | 
				
			||||||
export const NOTIFICATION_POLLS = 'notificationPolls'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const FILTER_REBLOG = 'reblog'
 | 
					 | 
				
			||||||
export const FILTER_REPLY = 'reply'
 | 
					 | 
				
			||||||
export const FILTER_MENTION = 'mention'
 | 
					 | 
				
			||||||
export const FILTER_FOLLOW = 'follow'
 | 
					 | 
				
			||||||
export const FILTER_FAVORITE = 'fav'
 | 
					 | 
				
			||||||
export const FILTER_POLL = 'poll'
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,3 @@
 | 
				
			||||||
import { get } from '../../_utils/lodash-lite'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function instanceMixins (Store) {
 | 
					export function instanceMixins (Store) {
 | 
				
			||||||
  Store.prototype.setComposeData = function (realm, obj) {
 | 
					  Store.prototype.setComposeData = function (realm, obj) {
 | 
				
			||||||
    let { composeData, currentInstance } = this.get()
 | 
					    let { composeData, currentInstance } = this.get()
 | 
				
			||||||
| 
						 | 
					@ -22,18 +20,4 @@ export function instanceMixins (Store) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.set({ composeData })
 | 
					    this.set({ composeData })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  Store.prototype.getInstanceSetting = function (instanceName, settingName, defaultValue) {
 | 
					 | 
				
			||||||
    let { instanceSettings } = this.get()
 | 
					 | 
				
			||||||
    return get(instanceSettings, [instanceName, settingName], defaultValue)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Store.prototype.setInstanceSetting = function (instanceName, settingName, value) {
 | 
					 | 
				
			||||||
    let { instanceSettings } = this.get()
 | 
					 | 
				
			||||||
    if (!instanceSettings[instanceName]) {
 | 
					 | 
				
			||||||
      instanceSettings[instanceName] = {}
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    instanceSettings[instanceName][settingName] = value
 | 
					 | 
				
			||||||
    this.set({ instanceSettings })
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,6 @@ const persistedState = {
 | 
				
			||||||
  largeInlineMedia: false,
 | 
					  largeInlineMedia: false,
 | 
				
			||||||
  instanceNameInSearch: '',
 | 
					  instanceNameInSearch: '',
 | 
				
			||||||
  instanceThemes: {},
 | 
					  instanceThemes: {},
 | 
				
			||||||
  instanceSettings: {},
 | 
					 | 
				
			||||||
  loggedInInstances: {},
 | 
					  loggedInInstances: {},
 | 
				
			||||||
  loggedInInstancesInOrder: [],
 | 
					  loggedInInstancesInOrder: [],
 | 
				
			||||||
  markMediaAsSensitive: false,
 | 
					  markMediaAsSensitive: false,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,8 @@ let meta = process.browser && document.getElementById('theThemeColor')
 | 
				
			||||||
let offlineStyle = process.browser && document.getElementById('theOfflineStyle')
 | 
					let offlineStyle = process.browser && document.getElementById('theOfflineStyle')
 | 
				
			||||||
let prefersDarkTheme = process.browser && window.matchMedia('(prefers-color-scheme: dark)').matches
 | 
					let prefersDarkTheme = process.browser && window.matchMedia('(prefers-color-scheme: dark)').matches
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const INLINE_THEME = 'default' // theme that does not require external CSS
 | 
					export const DEFAULT_LIGHT_THEME = 'default'
 | 
				
			||||||
export const DEFAULT_LIGHT_THEME = 'default' // theme that is shown by default
 | 
					export const DEFAULT_DARK_THEME = 'ozark'
 | 
				
			||||||
export const DEFAULT_DARK_THEME = 'ozark' // theme that is shown for prefers-color-scheme:dark
 | 
					 | 
				
			||||||
export const DEFAULT_THEME = prefersDarkTheme ? DEFAULT_DARK_THEME : DEFAULT_LIGHT_THEME
 | 
					export const DEFAULT_THEME = prefersDarkTheme ? DEFAULT_DARK_THEME : DEFAULT_LIGHT_THEME
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getExistingThemeLink () {
 | 
					function getExistingThemeLink () {
 | 
				
			||||||
| 
						 | 
					@ -39,7 +38,7 @@ function loadCSS (href) {
 | 
				
			||||||
export function switchToTheme (themeName = DEFAULT_THEME) {
 | 
					export function switchToTheme (themeName = DEFAULT_THEME) {
 | 
				
			||||||
  let themeColor = window.__themeColors[themeName]
 | 
					  let themeColor = window.__themeColors[themeName]
 | 
				
			||||||
  meta.content = themeColor || window.__themeColors[DEFAULT_THEME]
 | 
					  meta.content = themeColor || window.__themeColors[DEFAULT_THEME]
 | 
				
			||||||
  if (themeName !== INLINE_THEME) {
 | 
					  if (themeName !== DEFAULT_LIGHT_THEME) {
 | 
				
			||||||
    loadCSS(`/theme-${themeName}.css`)
 | 
					    loadCSS(`/theme-${themeName}.css`)
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    resetExistingTheme()
 | 
					    resetExistingTheme()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ self.addEventListener('activate', event => {
 | 
				
			||||||
    // delete old asset/ondemand caches
 | 
					    // delete old asset/ondemand caches
 | 
				
			||||||
    for (let key of keys) {
 | 
					    for (let key of keys) {
 | 
				
			||||||
      if (key !== ASSETS &&
 | 
					      if (key !== ASSETS &&
 | 
				
			||||||
        !key.startsWith('webpack_assets_')) {
 | 
					          !key.startsWith('webpack_assets_')) {
 | 
				
			||||||
        await caches.delete(key)
 | 
					        await caches.delete(key)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -131,71 +131,86 @@ async function showSimpleNotification (data) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function showRichNotification (data, notification) {
 | 
					async function showRichNotification (data, notification) {
 | 
				
			||||||
  const { icon, body } = data
 | 
					  const { origin } = new URL(data.icon)
 | 
				
			||||||
  const tag = notification.id
 | 
					 | 
				
			||||||
  const { origin } = self.location
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  switch (notification.type) {
 | 
					  switch (notification.type) {
 | 
				
			||||||
    case 'follow': {
 | 
					    case 'follow': {
 | 
				
			||||||
      await self.registration.showNotification(data.title, {
 | 
					      await self.registration.showNotification(data.title, {
 | 
				
			||||||
        icon,
 | 
					        icon: data.icon,
 | 
				
			||||||
        body,
 | 
					        body: data.body,
 | 
				
			||||||
        tag,
 | 
					        tag: notification.id,
 | 
				
			||||||
        data: {
 | 
					        data: {
 | 
				
			||||||
          url: `${origin}/accounts/${notification.account.id}`
 | 
					          url: `${self.location.origin}/accounts/${notification.account.id}`
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      break
 | 
					      break
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 'reblog':
 | 
					    case 'mention': {
 | 
				
			||||||
    case 'favourite':
 | 
					      const actions = [{
 | 
				
			||||||
    case 'poll':
 | 
					        action: 'favourite',
 | 
				
			||||||
      await self.registration.showNotification(data.title, {
 | 
					        title: 'Favourite'
 | 
				
			||||||
        icon,
 | 
					      }]
 | 
				
			||||||
        body,
 | 
					
 | 
				
			||||||
        tag,
 | 
					      if ('reply' in NotificationEvent.prototype) {
 | 
				
			||||||
        data: {
 | 
					        actions.splice(0, 0, {
 | 
				
			||||||
          url: `${origin}/statuses/${notification.status.id}`
 | 
					          action: 'reply',
 | 
				
			||||||
        }
 | 
					          type: 'text',
 | 
				
			||||||
      })
 | 
					          title: 'Reply'
 | 
				
			||||||
      break
 | 
					        })
 | 
				
			||||||
    case 'mention':
 | 
					      }
 | 
				
			||||||
      const isPublic = ['public', 'unlisted'].includes(notification.status.visibility)
 | 
					
 | 
				
			||||||
      const actions = [
 | 
					      if (['public', 'unlisted'].includes(notification.status.visibility)) {
 | 
				
			||||||
        {
 | 
					        actions.push({
 | 
				
			||||||
          action: 'favourite',
 | 
					 | 
				
			||||||
          title: 'Favorite'
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        isPublic && {
 | 
					 | 
				
			||||||
          action: 'reblog',
 | 
					          action: 'reblog',
 | 
				
			||||||
          title: 'Boost'
 | 
					          title: 'Boost'
 | 
				
			||||||
        }
 | 
					        })
 | 
				
			||||||
      ].filter(Boolean)
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await self.registration.showNotification(data.title, {
 | 
					      await self.registration.showNotification(data.title, {
 | 
				
			||||||
        icon,
 | 
					        icon: data.icon,
 | 
				
			||||||
        body,
 | 
					        body: data.body,
 | 
				
			||||||
        tag,
 | 
					        tag: notification.id,
 | 
				
			||||||
        data: {
 | 
					        data: {
 | 
				
			||||||
          instance: new URL(data.icon).origin,
 | 
					          instance: origin,
 | 
				
			||||||
          status_id: notification.status.id,
 | 
					          status_id: notification.status.id,
 | 
				
			||||||
          access_token: data.access_token,
 | 
					          access_token: data.access_token,
 | 
				
			||||||
          url: `${origin}/statuses/${notification.status.id}`
 | 
					          url: `${self.location.origin}/statuses/${notification.status.id}`
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        actions
 | 
					        actions
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      break
 | 
					      break
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 'reblog': {
 | 
				
			||||||
 | 
					      await self.registration.showNotification(data.title, {
 | 
				
			||||||
 | 
					        icon: data.icon,
 | 
				
			||||||
 | 
					        body: data.body,
 | 
				
			||||||
 | 
					        tag: notification.id,
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          url: `${self.location.origin}/statuses/${notification.status.id}`
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      break
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 'favourite': {
 | 
				
			||||||
 | 
					      await self.registration.showNotification(data.title, {
 | 
				
			||||||
 | 
					        icon: data.icon,
 | 
				
			||||||
 | 
					        body: data.body,
 | 
				
			||||||
 | 
					        tag: notification.id,
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          url: `${self.location.origin}/statuses/${notification.status.id}`
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      break
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const cloneNotification = notification => {
 | 
					const cloneNotification = notification => {
 | 
				
			||||||
  const clone = {}
 | 
					  const clone = { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Object.assign() does not work with notifications
 | 
					  // Object.assign() does not work with notifications
 | 
				
			||||||
  for (let k in notification) {
 | 
					  for (let k in notification) {
 | 
				
			||||||
    if (notification.hasOwnProperty(k)) {
 | 
					    clone[k] = notification[k]
 | 
				
			||||||
      clone[k] = notification[k]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return clone
 | 
					  return clone
 | 
				
			||||||
| 
						 | 
					@ -212,19 +227,21 @@ const updateNotificationWithoutAction = (notification, action) => {
 | 
				
			||||||
self.addEventListener('notificationclick', event => {
 | 
					self.addEventListener('notificationclick', event => {
 | 
				
			||||||
  event.waitUntil((async () => {
 | 
					  event.waitUntil((async () => {
 | 
				
			||||||
    switch (event.action) {
 | 
					    switch (event.action) {
 | 
				
			||||||
 | 
					      case 'reply': {
 | 
				
			||||||
 | 
					        await post(`${event.notification.data.instance}/api/v1/statuses/`, {
 | 
				
			||||||
 | 
					          status: event.reply,
 | 
				
			||||||
 | 
					          in_reply_to_id: event.notification.data.status_id
 | 
				
			||||||
 | 
					        }, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
 | 
				
			||||||
 | 
					        await updateNotificationWithoutAction(event.notification, 'reply')
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      case 'reblog': {
 | 
					      case 'reblog': {
 | 
				
			||||||
        const url = `${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/reblog`
 | 
					        await post(`${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/reblog`, null, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
 | 
				
			||||||
        await post(url, null, {
 | 
					 | 
				
			||||||
          'Authorization': `Bearer ${event.notification.data.access_token}`
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        await updateNotificationWithoutAction(event.notification, 'reblog')
 | 
					        await updateNotificationWithoutAction(event.notification, 'reblog')
 | 
				
			||||||
        break
 | 
					        break
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      case 'favourite': {
 | 
					      case 'favourite': {
 | 
				
			||||||
        const url = `${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/favourite`
 | 
					        await post(`${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/favourite`, null, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
 | 
				
			||||||
        await post(url, null, {
 | 
					 | 
				
			||||||
          'Authorization': `Bearer ${event.notification.data.access_token}`
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        await updateNotificationWithoutAction(event.notification, 'favourite')
 | 
					        await updateNotificationWithoutAction(event.notification, 'favourite')
 | 
				
			||||||
        break
 | 
					        break
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								static/apple-icon-120.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/apple-icon-120.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.5 KiB  | 
| 
		 Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB  | 
| 
						 | 
					@ -1,22 +1,22 @@
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  getUrl, notificationsTabAll, notificationsTabMentions,
 | 
					  getUrl, notificationFiltersAll, notificationFiltersMention,
 | 
				
			||||||
  notificationsNavButton, validateTimeline
 | 
					  notificationsNavButton, validateTimeline
 | 
				
			||||||
} from '../utils'
 | 
					} from '../utils'
 | 
				
			||||||
import { loginAsFoobar } from '../roles'
 | 
					import { loginAsFoobar } from '../roles'
 | 
				
			||||||
import { notificationsMentions, notifications } from '../fixtures'
 | 
					import { notificationsMentions, notifications } from '../fixtures'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fixture`033-notification-mentions.js`
 | 
					fixture`033-notification-filters.js`
 | 
				
			||||||
  .page`http://localhost:4002`
 | 
					  .page`http://localhost:4002`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('Shows notification mentions', async t => {
 | 
					test('Shows notification filters', async t => {
 | 
				
			||||||
  await loginAsFoobar(t)
 | 
					  await loginAsFoobar(t)
 | 
				
			||||||
  await t
 | 
					  await t
 | 
				
			||||||
    .click(notificationsNavButton)
 | 
					    .click(notificationsNavButton)
 | 
				
			||||||
    .expect(getUrl()).match(/\/notifications$/)
 | 
					    .expect(getUrl()).match(/\/notifications$/)
 | 
				
			||||||
    .click(notificationsTabMentions)
 | 
					    .click(notificationFiltersMention)
 | 
				
			||||||
    .expect(getUrl()).match(/\/notifications\/mentions$/)
 | 
					    .expect(getUrl()).match(/\/notifications\/mentions$/)
 | 
				
			||||||
  await validateTimeline(t, notificationsMentions)
 | 
					  await validateTimeline(t, notificationsMentions)
 | 
				
			||||||
  await t.click(notificationsTabAll)
 | 
					  await t.click(notificationFiltersAll)
 | 
				
			||||||
    .expect(getUrl()).match(/\/notifications$/)
 | 
					    .expect(getUrl()).match(/\/notifications$/)
 | 
				
			||||||
  await validateTimeline(t, notifications)
 | 
					  await validateTimeline(t, notifications)
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					@ -1,23 +0,0 @@
 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  validateTimeline, settingsNavButton, instanceSettingHomeReblogs, homeNavButton
 | 
					 | 
				
			||||||
} from '../utils'
 | 
					 | 
				
			||||||
import { loginAsFoobar } from '../roles'
 | 
					 | 
				
			||||||
import { homeTimeline } from '../fixtures'
 | 
					 | 
				
			||||||
import { Selector as $ } from 'testcafe'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fixture`034-home-timeline-filters.js`
 | 
					 | 
				
			||||||
  .page`http://localhost:4002`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test('Filters reblogs from home timeline', async t => {
 | 
					 | 
				
			||||||
  await loginAsFoobar(t)
 | 
					 | 
				
			||||||
  await t
 | 
					 | 
				
			||||||
    .click(settingsNavButton)
 | 
					 | 
				
			||||||
    .click($('a').withText('Instances'))
 | 
					 | 
				
			||||||
    .click($('a').withText('localhost:3000'))
 | 
					 | 
				
			||||||
    .click(instanceSettingHomeReblogs)
 | 
					 | 
				
			||||||
    .expect(instanceSettingHomeReblogs.checked).notOk()
 | 
					 | 
				
			||||||
    .click(homeNavButton)
 | 
					 | 
				
			||||||
  await validateTimeline(t, homeTimeline.filter(({ content }) => {
 | 
					 | 
				
			||||||
    return content !== 'pinned toot 1'
 | 
					 | 
				
			||||||
  }))
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,48 +0,0 @@
 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  validateTimeline,
 | 
					 | 
				
			||||||
  settingsNavButton,
 | 
					 | 
				
			||||||
  instanceSettingNotificationReblogs,
 | 
					 | 
				
			||||||
  notificationsNavButton,
 | 
					 | 
				
			||||||
  instanceSettingNotificationFavs,
 | 
					 | 
				
			||||||
  instanceSettingNotificationFollows,
 | 
					 | 
				
			||||||
  instanceSettingNotificationMentions
 | 
					 | 
				
			||||||
} from '../utils'
 | 
					 | 
				
			||||||
import { loginAsFoobar } from '../roles'
 | 
					 | 
				
			||||||
import { notifications } from '../fixtures'
 | 
					 | 
				
			||||||
import { Selector as $ } from 'testcafe'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fixture`035-notification-timeline-filters.js`
 | 
					 | 
				
			||||||
  .page`http://localhost:4002`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function setSettingAndGoToNotifications (t, setting) {
 | 
					 | 
				
			||||||
  return t.click(settingsNavButton)
 | 
					 | 
				
			||||||
    .click($('a').withText('Instances'))
 | 
					 | 
				
			||||||
    .click($('a').withText('localhost:3000'))
 | 
					 | 
				
			||||||
    .click(setting)
 | 
					 | 
				
			||||||
    .expect(setting.checked).notOk()
 | 
					 | 
				
			||||||
    .click(notificationsNavButton)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test('Filters reblogs from notification timeline', async t => {
 | 
					 | 
				
			||||||
  await loginAsFoobar(t)
 | 
					 | 
				
			||||||
  await setSettingAndGoToNotifications(t, instanceSettingNotificationReblogs)
 | 
					 | 
				
			||||||
  await validateTimeline(t, notifications.filter(_ => !_.rebloggedBy))
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test('Filters favs from notification timeline', async t => {
 | 
					 | 
				
			||||||
  await loginAsFoobar(t)
 | 
					 | 
				
			||||||
  await setSettingAndGoToNotifications(t, instanceSettingNotificationFavs)
 | 
					 | 
				
			||||||
  await validateTimeline(t, notifications.filter(_ => !_.favoritedBy))
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test('Filters follows from notification timeline', async t => {
 | 
					 | 
				
			||||||
  await loginAsFoobar(t)
 | 
					 | 
				
			||||||
  await setSettingAndGoToNotifications(t, instanceSettingNotificationFollows)
 | 
					 | 
				
			||||||
  await validateTimeline(t, notifications.filter(_ => !_.followedBy))
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test('Filters mentions from notification timeline', async t => {
 | 
					 | 
				
			||||||
  await loginAsFoobar(t)
 | 
					 | 
				
			||||||
  await setSettingAndGoToNotifications(t, instanceSettingNotificationMentions)
 | 
					 | 
				
			||||||
  await validateTimeline(t, notifications.filter(_ => !_.content))
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  getNthStatusContent,
 | 
					  getNthStatusContent,
 | 
				
			||||||
  getUrl, notificationsTabAll, notificationsTabMentions,
 | 
					  getUrl, notificationFiltersAll, notificationFiltersMention,
 | 
				
			||||||
  notificationsNavButton, sleep
 | 
					  notificationsNavButton, sleep
 | 
				
			||||||
} from '../utils'
 | 
					} from '../utils'
 | 
				
			||||||
import { loginAsFoobar } from '../roles'
 | 
					import { loginAsFoobar } from '../roles'
 | 
				
			||||||
import { favoriteStatusAs, postAs } from '../serverActions'
 | 
					import { favoriteStatusAs, postAs } from '../serverActions'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fixture`123-notification-mentions.js`
 | 
					fixture`123-notification-filters.js`
 | 
				
			||||||
  .page`http://localhost:4002`
 | 
					  .page`http://localhost:4002`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// maybe in the "mentions" view it should prevent the notification icon from showing (1), (2) etc
 | 
					// maybe in the "mentions" view it should prevent the notification icon from showing (1), (2) etc
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ test('Handles incoming notifications that are mentions', async t => {
 | 
				
			||||||
  await t
 | 
					  await t
 | 
				
			||||||
    .click(notificationsNavButton)
 | 
					    .click(notificationsNavButton)
 | 
				
			||||||
    .expect(getUrl()).match(/\/notifications$/)
 | 
					    .expect(getUrl()).match(/\/notifications$/)
 | 
				
			||||||
    .click(notificationsTabMentions)
 | 
					    .click(notificationFiltersMention)
 | 
				
			||||||
    .expect(getUrl()).match(/\/notifications\/mentions$/)
 | 
					    .expect(getUrl()).match(/\/notifications\/mentions$/)
 | 
				
			||||||
  await sleep(2000)
 | 
					  await sleep(2000)
 | 
				
			||||||
  await postAs('admin', 'hey @foobar I am mentioning you')
 | 
					  await postAs('admin', 'hey @foobar I am mentioning you')
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ test('Handles incoming notifications that are mentions', async t => {
 | 
				
			||||||
      timeout
 | 
					      timeout
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .expect(getNthStatusContent(1).innerText).contains('hey @foobar I am mentioning you')
 | 
					    .expect(getNthStatusContent(1).innerText).contains('hey @foobar I am mentioning you')
 | 
				
			||||||
    .click(notificationsTabAll)
 | 
					    .click(notificationFiltersAll)
 | 
				
			||||||
    .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications (current page)', { timeout })
 | 
					    .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications (current page)', { timeout })
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ test('Handles incoming notifications that are not mentions', async t => {
 | 
				
			||||||
  await t
 | 
					  await t
 | 
				
			||||||
    .click(notificationsNavButton)
 | 
					    .click(notificationsNavButton)
 | 
				
			||||||
    .expect(getUrl()).match(/\/notifications$/)
 | 
					    .expect(getUrl()).match(/\/notifications$/)
 | 
				
			||||||
    .click(notificationsTabMentions)
 | 
					    .click(notificationFiltersMention)
 | 
				
			||||||
    .expect(getUrl()).match(/\/notifications\/mentions$/)
 | 
					    .expect(getUrl()).match(/\/notifications\/mentions$/)
 | 
				
			||||||
  await sleep(2000)
 | 
					  await sleep(2000)
 | 
				
			||||||
  await postAs('admin', 'woot I am mentioning you again @foobar')
 | 
					  await postAs('admin', 'woot I am mentioning you again @foobar')
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ test('Handles incoming notifications that are not mentions', async t => {
 | 
				
			||||||
  await sleep(2000)
 | 
					  await sleep(2000)
 | 
				
			||||||
  await t
 | 
					  await t
 | 
				
			||||||
    .expect(getNthStatusContent(1).innerText).contains('woot I am mentioning you again @foobar')
 | 
					    .expect(getNthStatusContent(1).innerText).contains('woot I am mentioning you again @foobar')
 | 
				
			||||||
    .click(notificationsTabAll)
 | 
					    .click(notificationFiltersAll)
 | 
				
			||||||
    .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications (current page)', { timeout })
 | 
					    .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications (current page)', { timeout })
 | 
				
			||||||
  await t
 | 
					  await t
 | 
				
			||||||
    .expect(getNthStatusContent(1).innerText).contains('this is a post that I hope somebody will favorite')
 | 
					    .expect(getNthStatusContent(1).innerText).contains('this is a post that I hope somebody will favorite')
 | 
				
			||||||
| 
						 | 
					@ -1,29 +0,0 @@
 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  settingsNavButton, instanceSettingHomeReblogs, homeNavButton, sleep, getNthStatusContent
 | 
					 | 
				
			||||||
} from '../utils'
 | 
					 | 
				
			||||||
import { loginAsFoobar } from '../roles'
 | 
					 | 
				
			||||||
import { Selector as $ } from 'testcafe'
 | 
					 | 
				
			||||||
import { postAs, reblogStatusAs } from '../serverActions'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fixture`124-home-timeline-filters.js`
 | 
					 | 
				
			||||||
  .page`http://localhost:4002`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test('Filters favs from home timeline', async t => {
 | 
					 | 
				
			||||||
  await postAs('foobar', 'Nobody should boost this')
 | 
					 | 
				
			||||||
  await sleep(1000)
 | 
					 | 
				
			||||||
  let { id: statusId } = await postAs('quux', 'I hope someone cool boosts this')
 | 
					 | 
				
			||||||
  await reblogStatusAs('admin', statusId)
 | 
					 | 
				
			||||||
  await sleep(2000)
 | 
					 | 
				
			||||||
  await loginAsFoobar(t)
 | 
					 | 
				
			||||||
  await t
 | 
					 | 
				
			||||||
    .expect(getNthStatusContent(1).innerText).contains('I hope someone cool boosts this')
 | 
					 | 
				
			||||||
    .expect(getNthStatusContent(2).innerText).contains('Nobody should boost this')
 | 
					 | 
				
			||||||
    .click(settingsNavButton)
 | 
					 | 
				
			||||||
    .click($('a').withText('Instances'))
 | 
					 | 
				
			||||||
    .click($('a').withText('localhost:3000'))
 | 
					 | 
				
			||||||
    .click(instanceSettingHomeReblogs)
 | 
					 | 
				
			||||||
    .expect(instanceSettingHomeReblogs.checked).notOk()
 | 
					 | 
				
			||||||
    .click(homeNavButton)
 | 
					 | 
				
			||||||
  await t
 | 
					 | 
				
			||||||
    .expect(getNthStatusContent(1).innerText).contains('Nobody should boost this')
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
| 
						 | 
					@ -64,14 +64,8 @@ export const accountProfileFilterStatuses = $('.account-profile-filters li:nth-c
 | 
				
			||||||
export const accountProfileFilterStatusesAndReplies = $('.account-profile-filters li:nth-child(2)')
 | 
					export const accountProfileFilterStatusesAndReplies = $('.account-profile-filters li:nth-child(2)')
 | 
				
			||||||
export const accountProfileFilterMedia = $('.account-profile-filters li:nth-child(3)')
 | 
					export const accountProfileFilterMedia = $('.account-profile-filters li:nth-child(3)')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const notificationsTabAll = $('.notification-filters li:nth-child(1)')
 | 
					export const notificationFiltersAll = $('.notification-filters li:nth-child(1)')
 | 
				
			||||||
export const notificationsTabMentions = $('.notification-filters li:nth-child(2)')
 | 
					export const notificationFiltersMention = $('.notification-filters li:nth-child(2)')
 | 
				
			||||||
 | 
					 | 
				
			||||||
export const instanceSettingHomeReblogs = $('#instance-option-homeReblogs')
 | 
					 | 
				
			||||||
export const instanceSettingNotificationFollows = $('#instance-option-notificationFollows')
 | 
					 | 
				
			||||||
export const instanceSettingNotificationFavs = $('#instance-option-notificationFavs')
 | 
					 | 
				
			||||||
export const instanceSettingNotificationReblogs = $('#instance-option-notificationReblogs')
 | 
					 | 
				
			||||||
export const instanceSettingNotificationMentions = $('#instance-option-notificationMentions')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getComposeModalNthMediaAltInput (n) {
 | 
					export function getComposeModalNthMediaAltInput (n) {
 | 
				
			||||||
  return $(`.modal-dialog .compose-media:nth-child(${n}) .compose-media-alt input`)
 | 
					  return $(`.modal-dialog .compose-media:nth-child(${n}) .compose-media-alt input`)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										137
									
								
								yarn.lock
									
										
									
									
									
								
							
							
						
						
									
										137
									
								
								yarn.lock
									
										
									
									
									
								
							| 
						 | 
					@ -642,15 +642,13 @@ assert@^1.1.1:
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    util "0.10.3"
 | 
					    util "0.10.3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
assert@^2.0.0:
 | 
					assert@^1.5.0:
 | 
				
			||||||
  version "2.0.0"
 | 
					  version "1.5.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32"
 | 
					  resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
 | 
				
			||||||
  integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==
 | 
					  integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    es6-object-assign "^1.1.0"
 | 
					    object-assign "^4.1.1"
 | 
				
			||||||
    is-nan "^1.2.1"
 | 
					    util "0.10.3"
 | 
				
			||||||
    object-is "^1.0.1"
 | 
					 | 
				
			||||||
    util "^0.12.0"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
assertion-error@^1.0.1, assertion-error@^1.1.0:
 | 
					assertion-error@^1.0.1, assertion-error@^1.1.0:
 | 
				
			||||||
  version "1.1.0"
 | 
					  version "1.1.0"
 | 
				
			||||||
| 
						 | 
					@ -2033,11 +2031,6 @@ commander@^2.18.0, commander@^2.8.1:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
 | 
					  resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
 | 
				
			||||||
  integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
 | 
					  integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
commander@^2.19.0:
 | 
					 | 
				
			||||||
  version "2.20.0"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
 | 
					 | 
				
			||||||
  integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
commondir@^1.0.1:
 | 
					commondir@^1.0.1:
 | 
				
			||||||
  version "1.0.1"
 | 
					  version "1.0.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
 | 
					  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
 | 
				
			||||||
| 
						 | 
					@ -2459,7 +2452,7 @@ deep-is@~0.1.3:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
 | 
					  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
 | 
				
			||||||
  integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
 | 
					  integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define-properties@^1.1.1, define-properties@^1.1.2, define-properties@^1.1.3:
 | 
					define-properties@^1.1.2, define-properties@^1.1.3:
 | 
				
			||||||
  version "1.1.3"
 | 
					  version "1.1.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
 | 
					  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
 | 
				
			||||||
  integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
 | 
					  integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
 | 
				
			||||||
| 
						 | 
					@ -2805,11 +2798,6 @@ es-to-primitive@^1.2.0:
 | 
				
			||||||
    is-date-object "^1.0.1"
 | 
					    is-date-object "^1.0.1"
 | 
				
			||||||
    is-symbol "^1.0.2"
 | 
					    is-symbol "^1.0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
es6-object-assign@^1.1.0:
 | 
					 | 
				
			||||||
  version "1.1.0"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
 | 
					 | 
				
			||||||
  integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
escape-html@^1.0.3, escape-html@~1.0.3:
 | 
					escape-html@^1.0.3, escape-html@~1.0.3:
 | 
				
			||||||
  version "1.0.3"
 | 
					  version "1.0.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
 | 
					  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
 | 
				
			||||||
| 
						 | 
					@ -2972,10 +2960,10 @@ eslint@~5.4.0:
 | 
				
			||||||
    table "^4.0.3"
 | 
					    table "^4.0.3"
 | 
				
			||||||
    text-table "^0.2.0"
 | 
					    text-table "^0.2.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
esm@^3.2.25:
 | 
					esm@^3.2.22:
 | 
				
			||||||
  version "3.2.25"
 | 
					  version "3.2.22"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
 | 
					  resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.22.tgz#5062c2e22fee3ccfee4e8f20da768330da90d6e3"
 | 
				
			||||||
  integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
 | 
					  integrity sha512-z8YG7U44L82j1XrdEJcqZOLUnjxco8pO453gKOlaMD1/md1n/5QrscAmYG+oKUspsmDLuBFZrpbxI6aQ67yRxA==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
esotope-hammerhead@^0.2.1:
 | 
					esotope-hammerhead@^0.2.1:
 | 
				
			||||||
  version "0.2.1"
 | 
					  version "0.2.1"
 | 
				
			||||||
| 
						 | 
					@ -4020,11 +4008,6 @@ is-accessor-descriptor@^1.0.0:
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    kind-of "^6.0.0"
 | 
					    kind-of "^6.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
is-arguments@^1.0.4:
 | 
					 | 
				
			||||||
  version "1.0.4"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
 | 
					 | 
				
			||||||
  integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
is-arrayish@^0.2.1:
 | 
					is-arrayish@^0.2.1:
 | 
				
			||||||
  version "0.2.1"
 | 
					  version "0.2.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
 | 
					  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
 | 
				
			||||||
| 
						 | 
					@ -4161,11 +4144,6 @@ is-fullwidth-code-point@^2.0.0:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
 | 
					  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
 | 
				
			||||||
  integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
 | 
					  integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
is-generator-function@^1.0.7:
 | 
					 | 
				
			||||||
  version "1.0.7"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
 | 
					 | 
				
			||||||
  integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
is-glob@^2.0.1:
 | 
					is-glob@^2.0.1:
 | 
				
			||||||
  version "2.0.1"
 | 
					  version "2.0.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
 | 
					  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
 | 
				
			||||||
| 
						 | 
					@ -4199,13 +4177,6 @@ is-jquery-obj@^0.1.0:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-jquery-obj/-/is-jquery-obj-0.1.1.tgz#e8d9cc9737b1ab0733b50303e33a38ed7cc2f60b"
 | 
					  resolved "https://registry.yarnpkg.com/is-jquery-obj/-/is-jquery-obj-0.1.1.tgz#e8d9cc9737b1ab0733b50303e33a38ed7cc2f60b"
 | 
				
			||||||
  integrity sha512-18toSebUVF7y717dgw/Dzn6djOCqrkiDp3MhB8P6TdKyCVkbD1ZwE7Uz8Hwx6hUPTvKjbyYH9ncXT4ts4qLaSA==
 | 
					  integrity sha512-18toSebUVF7y717dgw/Dzn6djOCqrkiDp3MhB8P6TdKyCVkbD1ZwE7Uz8Hwx6hUPTvKjbyYH9ncXT4ts4qLaSA==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
is-nan@^1.2.1:
 | 
					 | 
				
			||||||
  version "1.2.1"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2"
 | 
					 | 
				
			||||||
  integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI=
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    define-properties "^1.1.1"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
is-number@^3.0.0:
 | 
					is-number@^3.0.0:
 | 
				
			||||||
  version "3.0.0"
 | 
					  version "3.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
 | 
					  resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
 | 
				
			||||||
| 
						 | 
					@ -4315,10 +4286,10 @@ isstream@~0.1.2:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
 | 
					  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
 | 
				
			||||||
  integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 | 
					  integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
jest-worker@^24.6.0:
 | 
					jest-worker@^24.0.0:
 | 
				
			||||||
  version "24.6.0"
 | 
					  version "24.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3"
 | 
					  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d"
 | 
				
			||||||
  integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==
 | 
					  integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    merge-stream "^1.0.1"
 | 
					    merge-stream "^1.0.1"
 | 
				
			||||||
    supports-color "^6.1.0"
 | 
					    supports-color "^6.1.0"
 | 
				
			||||||
| 
						 | 
					@ -5275,11 +5246,6 @@ object-copy@^0.1.0:
 | 
				
			||||||
    define-property "^0.2.5"
 | 
					    define-property "^0.2.5"
 | 
				
			||||||
    kind-of "^3.0.3"
 | 
					    kind-of "^3.0.3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
object-is@^1.0.1:
 | 
					 | 
				
			||||||
  version "1.0.1"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6"
 | 
					 | 
				
			||||||
  integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
object-keys@^1.0.11:
 | 
					object-keys@^1.0.11:
 | 
				
			||||||
  version "1.1.0"
 | 
					  version "1.1.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032"
 | 
					  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032"
 | 
				
			||||||
| 
						 | 
					@ -5307,16 +5273,6 @@ object.assign@4.1.0:
 | 
				
			||||||
    has-symbols "^1.0.0"
 | 
					    has-symbols "^1.0.0"
 | 
				
			||||||
    object-keys "^1.0.11"
 | 
					    object-keys "^1.0.11"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
object.entries@^1.1.0:
 | 
					 | 
				
			||||||
  version "1.1.0"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519"
 | 
					 | 
				
			||||||
  integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    define-properties "^1.1.3"
 | 
					 | 
				
			||||||
    es-abstract "^1.12.0"
 | 
					 | 
				
			||||||
    function-bind "^1.1.1"
 | 
					 | 
				
			||||||
    has "^1.0.3"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
object.getownpropertydescriptors@^2.0.3:
 | 
					object.getownpropertydescriptors@^2.0.3:
 | 
				
			||||||
  version "2.0.3"
 | 
					  version "2.0.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
 | 
					  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
 | 
				
			||||||
| 
						 | 
					@ -6396,15 +6352,15 @@ rollup-plugin-replace@^2.2.0:
 | 
				
			||||||
    magic-string "^0.25.2"
 | 
					    magic-string "^0.25.2"
 | 
				
			||||||
    rollup-pluginutils "^2.6.0"
 | 
					    rollup-pluginutils "^2.6.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rollup-plugin-terser@^5.0.0:
 | 
					rollup-plugin-terser@^4.0.4:
 | 
				
			||||||
  version "5.0.0"
 | 
					  version "4.0.4"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.0.0.tgz#ac50fdb703b580447a7e6b1692aeed515a6be8cf"
 | 
					  resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-4.0.4.tgz#6f661ef284fa7c27963d242601691dc3d23f994e"
 | 
				
			||||||
  integrity sha512-W+jJ4opYnlmNyVW0vtRufs+EGf68BIJ7bnOazgz8mgz8pA9lUyrEifAhPs5y9M16wFeAyBGaRjKip4dnFBtXaw==
 | 
					  integrity sha512-wPANT5XKVJJ8RDUN0+wIr7UPd0lIXBo4UdJ59VmlPCtlFsE20AM+14pe+tk7YunCsWEiuzkDBY3QIkSCjtrPXg==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    "@babel/code-frame" "^7.0.0"
 | 
					    "@babel/code-frame" "^7.0.0"
 | 
				
			||||||
    jest-worker "^24.6.0"
 | 
					    jest-worker "^24.0.0"
 | 
				
			||||||
    serialize-javascript "^1.7.0"
 | 
					    serialize-javascript "^1.6.1"
 | 
				
			||||||
    terser "^4.0.0"
 | 
					    terser "^3.14.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rollup-pluginutils@^2.6.0:
 | 
					rollup-pluginutils@^2.6.0:
 | 
				
			||||||
  version "2.6.0"
 | 
					  version "2.6.0"
 | 
				
			||||||
| 
						 | 
					@ -6556,16 +6512,11 @@ send@0.16.2:
 | 
				
			||||||
    range-parser "~1.2.0"
 | 
					    range-parser "~1.2.0"
 | 
				
			||||||
    statuses "~1.4.0"
 | 
					    statuses "~1.4.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
serialize-javascript@^1.4.0:
 | 
					serialize-javascript@^1.4.0, serialize-javascript@^1.6.1:
 | 
				
			||||||
  version "1.6.1"
 | 
					  version "1.6.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879"
 | 
					  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879"
 | 
				
			||||||
  integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==
 | 
					  integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
serialize-javascript@^1.7.0:
 | 
					 | 
				
			||||||
  version "1.7.0"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65"
 | 
					 | 
				
			||||||
  integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
serve-static@1.13.2:
 | 
					serve-static@1.13.2:
 | 
				
			||||||
  version "1.13.2"
 | 
					  version "1.13.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
 | 
					  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
 | 
				
			||||||
| 
						 | 
					@ -6724,14 +6675,6 @@ source-map-support@^0.5.5, source-map-support@^0.5.9, source-map-support@~0.5.6,
 | 
				
			||||||
    buffer-from "^1.0.0"
 | 
					    buffer-from "^1.0.0"
 | 
				
			||||||
    source-map "^0.6.0"
 | 
					    source-map "^0.6.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
source-map-support@~0.5.10:
 | 
					 | 
				
			||||||
  version "0.5.12"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
 | 
					 | 
				
			||||||
  integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    buffer-from "^1.0.0"
 | 
					 | 
				
			||||||
    source-map "^0.6.0"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
source-map-url@^0.4.0:
 | 
					source-map-url@^0.4.0:
 | 
				
			||||||
  version "0.4.0"
 | 
					  version "0.4.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
 | 
					  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
 | 
				
			||||||
| 
						 | 
					@ -7206,16 +7149,7 @@ terser-webpack-plugin@^1.2.3:
 | 
				
			||||||
    webpack-sources "^1.1.0"
 | 
					    webpack-sources "^1.1.0"
 | 
				
			||||||
    worker-farm "^1.5.2"
 | 
					    worker-farm "^1.5.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
terser@^3.16.1:
 | 
					terser@^3.14.1, terser@^3.8.1:
 | 
				
			||||||
  version "3.16.1"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/terser/-/terser-3.16.1.tgz#5b0dd4fa1ffd0b0b43c2493b2c364fd179160493"
 | 
					 | 
				
			||||||
  integrity sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    commander "~2.17.1"
 | 
					 | 
				
			||||||
    source-map "~0.6.1"
 | 
					 | 
				
			||||||
    source-map-support "~0.5.9"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
terser@^3.8.1:
 | 
					 | 
				
			||||||
  version "3.14.1"
 | 
					  version "3.14.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32"
 | 
					  resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32"
 | 
				
			||||||
  integrity sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw==
 | 
					  integrity sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw==
 | 
				
			||||||
| 
						 | 
					@ -7224,14 +7158,14 @@ terser@^3.8.1:
 | 
				
			||||||
    source-map "~0.6.1"
 | 
					    source-map "~0.6.1"
 | 
				
			||||||
    source-map-support "~0.5.6"
 | 
					    source-map-support "~0.5.6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
terser@^4.0.0:
 | 
					terser@^3.16.1:
 | 
				
			||||||
  version "4.0.0"
 | 
					  version "3.16.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.0.tgz#ef356f6f359a963e2cc675517f21c1c382877374"
 | 
					  resolved "https://registry.yarnpkg.com/terser/-/terser-3.16.1.tgz#5b0dd4fa1ffd0b0b43c2493b2c364fd179160493"
 | 
				
			||||||
  integrity sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA==
 | 
					  integrity sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    commander "^2.19.0"
 | 
					    commander "~2.17.1"
 | 
				
			||||||
    source-map "~0.6.1"
 | 
					    source-map "~0.6.1"
 | 
				
			||||||
    source-map-support "~0.5.10"
 | 
					    source-map-support "~0.5.9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
testcafe-browser-tools@1.6.8:
 | 
					testcafe-browser-tools@1.6.8:
 | 
				
			||||||
  version "1.6.8"
 | 
					  version "1.6.8"
 | 
				
			||||||
| 
						 | 
					@ -7780,17 +7714,6 @@ util@^0.11.0:
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    inherits "2.0.3"
 | 
					    inherits "2.0.3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
util@^0.12.0:
 | 
					 | 
				
			||||||
  version "0.12.0"
 | 
					 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/util/-/util-0.12.0.tgz#bb5e3d29ba2703c7add0ad337003be3ca477798a"
 | 
					 | 
				
			||||||
  integrity sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					 | 
				
			||||||
    inherits "2.0.3"
 | 
					 | 
				
			||||||
    is-arguments "^1.0.4"
 | 
					 | 
				
			||||||
    is-generator-function "^1.0.7"
 | 
					 | 
				
			||||||
    object.entries "^1.1.0"
 | 
					 | 
				
			||||||
    safe-buffer "^5.1.2"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
utils-merge@1.0.1:
 | 
					utils-merge@1.0.1:
 | 
				
			||||||
  version "1.0.1"
 | 
					  version "1.0.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
 | 
					  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue