Compare commits
11 Commits
9e6bc60abe
...
12c5b732ae
Author | SHA1 | Date |
---|---|---|
Nolan Lawson | 12c5b732ae | |
Nolan Lawson | a17948cf99 | |
Nolan Lawson | 92bff6caaa | |
Nolan Lawson | 02689bec93 | |
Nolan Lawson | c18168d913 | |
sgenoud | af955492e8 | |
Nolan Lawson | 692e8b57c3 | |
Nolan Lawson | d92bd2e94b | |
greenkeeper[bot] | 5178650e78 | |
greenkeeper[bot] | 9862858b2e | |
Cătălin Mariș | cdade05315 |
|
@ -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.22",
|
"esm": "^3.2.25",
|
||||||
"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": "^4.0.4",
|
"rollup-plugin-terser": "^5.0.0",
|
||||||
"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": "^1.5.0",
|
"assert": "^2.0.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,8 +10,7 @@
|
||||||
|
|
||||||
<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" sizes="120x120" href="/apple-icon-120.png" >
|
<link rel="apple-touch-icon" href="/apple-icon.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 { DEFAULT_LIGHT_THEME, DEFAULT_THEME, switchToTheme } from '../routes/_utils/themeEngine'
|
import { INLINE_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 !== DEFAULT_LIGHT_THEME) {
|
if (theme !== INLINE_THEME) {
|
||||||
// switch theme ASAP to minimize flash of default theme
|
// switch theme ASAP to minimize flash of default theme
|
||||||
switchToTheme(theme)
|
switchToTheme(theme)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<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>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<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>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<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,18 +4,21 @@
|
||||||
{: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" disabled="{!pushNotificationsSupport}" ref:pushNotificationsForm aria-label="Push notification settings">
|
<form id="push-notification-settings"
|
||||||
<input type="checkbox" id="push-notifications-follow" name="follow" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
|
disabled="{!pushNotificationsSupport}"
|
||||||
<label for="push-notifications-follow">New followers</label>
|
ref:form
|
||||||
|
aria-label="Push notification settings">
|
||||||
|
{#each options as option, i (option.key)}
|
||||||
|
{#if i > 0}
|
||||||
<br>
|
<br>
|
||||||
<input type="checkbox" id="push-notifications-favourite" name="favourite" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
|
{/if}
|
||||||
<label for="push-notifications-favourite">Favourites</label>
|
<input type="checkbox"
|
||||||
<br>
|
id="push-notifications-{option.key}"
|
||||||
<input type="checkbox" id="push-notifications-reblog" name="reblog" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
|
name="{option.key}"
|
||||||
<label for="push-notifications-reblog">Boosts</label>
|
disabled="{!pushNotificationsSupport}"
|
||||||
<br>
|
on:change="onPushSettingsChange(event)">
|
||||||
<input type="checkbox" id="push-notifications-mention" name="mention" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
|
<label for="push-notifications-{option.key}">{option.label}</label>
|
||||||
<label for="push-notifications-mention">Mentions</label>
|
{/each}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
@ -27,11 +30,11 @@
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
}
|
}
|
||||||
.push-notifications form[disabled="true"] {
|
form[disabled="true"] {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.push-notifications p {
|
p {
|
||||||
margin: 0;
|
margin: 0 0 10px 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
@ -40,33 +43,56 @@
|
||||||
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 } = this.get()
|
let { instanceName, options } = this.get()
|
||||||
await updatePushSubscriptionForInstance(instanceName)
|
await updatePushSubscriptionForInstance(instanceName)
|
||||||
|
|
||||||
const form = this.refs.pushNotificationsForm
|
const { form } = this.refs
|
||||||
const { pushSubscription } = this.store.get()
|
const { pushSubscription } = this.store.get()
|
||||||
|
|
||||||
form.elements.follow.checked = pushSubscription && pushSubscription.alerts && pushSubscription.alerts.follow
|
for (let { key } of options) {
|
||||||
form.elements.favourite.checked = pushSubscription && pushSubscription.alerts && pushSubscription.alerts.favourite
|
form.elements[key].checked = get(pushSubscription, ['alerts', key])
|
||||||
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 } = this.get()
|
const { instanceName, options } = this.get()
|
||||||
const form = this.refs.pushNotificationsForm
|
const { form } = this.refs
|
||||||
const alerts = {
|
const alerts = {}
|
||||||
follow: form.elements.follow.checked,
|
|
||||||
favourite: form.elements.favourite.checked,
|
for (let { key } of options) {
|
||||||
reblog: form.elements.reblog.checked,
|
alerts[key] = form.elements[key].checked
|
||||||
mention: form.elements.mention.checked
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
{#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}
|
||||||
|
@ -58,6 +61,7 @@
|
||||||
"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";
|
||||||
|
@ -92,6 +96,7 @@
|
||||||
"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";
|
||||||
|
@ -119,6 +124,7 @@
|
||||||
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'
|
||||||
|
@ -170,6 +176,7 @@
|
||||||
StatusMediaAttachments,
|
StatusMediaAttachments,
|
||||||
StatusContent,
|
StatusContent,
|
||||||
StatusCard,
|
StatusCard,
|
||||||
|
StatusPoll,
|
||||||
StatusSpoiler,
|
StatusSpoiler,
|
||||||
StatusComposeBox,
|
StatusComposeBox,
|
||||||
StatusMentions,
|
StatusMentions,
|
||||||
|
@ -261,6 +268,9 @@
|
||||||
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 &&
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<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,6 +59,22 @@
|
||||||
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 () {
|
||||||
|
@ -127,9 +143,56 @@
|
||||||
timelineValue !== $firstTimelineItemId &&
|
timelineValue !== $firstTimelineItemId &&
|
||||||
timelineValue
|
timelineValue
|
||||||
),
|
),
|
||||||
itemIds: ({ $timelineItemSummaries }) => (
|
currentInstanceSettings: ({ $currentInstance, $instanceSettings }) => (
|
||||||
// TODO: filter
|
$instanceSettings[$currentInstance] || {}
|
||||||
$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-mark-media-sensitive"
|
|
||||||
bind:checked="$markMediaAsSensitive" on:change="onChange(event)">
|
|
||||||
<label for="choice-mark-media-sensitive">Always mark media as sensitive</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-group">
|
<div class="setting-group">
|
||||||
<input type="checkbox" id="choice-never-mark-media-sensitive"
|
<input type="checkbox" id="choice-never-mark-media-sensitive"
|
||||||
bind:checked="$neverMarkMediaAsSensitive" on:change="onChange(event)">
|
bind:checked="$neverMarkMediaAsSensitive" on:change="onChange(event)">
|
||||||
<label for="choice-never-mark-media-sensitive">Never mark media as sensitive</label>
|
<label for="choice-never-mark-media-sensitive">Show sensitive media by default</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-group">
|
||||||
|
<input type="checkbox" id="choice-mark-media-sensitive"
|
||||||
|
bind:checked="$markMediaAsSensitive" on:change="onChange(event)">
|
||||||
|
<label for="choice-mark-media-sensitive">Hide all media by default</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,9 +4,13 @@
|
||||||
{#if verifyCredentials}
|
{#if verifyCredentials}
|
||||||
<h2>Logged in as:</h2>
|
<h2>Logged in as:</h2>
|
||||||
<InstanceUserProfile {verifyCredentials} />
|
<InstanceUserProfile {verifyCredentials} />
|
||||||
<h2>Push notifications:</h2>
|
<h2>Home timeline filters</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} />
|
||||||
|
@ -23,6 +27,8 @@
|
||||||
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'
|
||||||
|
@ -43,7 +49,9 @@
|
||||||
InstanceUserProfile,
|
InstanceUserProfile,
|
||||||
PushNotificationSettings,
|
PushNotificationSettings,
|
||||||
ThemeSettings,
|
ThemeSettings,
|
||||||
InstanceActions
|
InstanceActions,
|
||||||
|
HomeTimelineFilterSettings,
|
||||||
|
NotificationFilterSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -0,0 +1,15 @@
|
||||||
|
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,3 +1,5 @@
|
||||||
|
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()
|
||||||
|
@ -20,4 +22,18 @@ 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,6 +19,7 @@ const persistedState = {
|
||||||
largeInlineMedia: false,
|
largeInlineMedia: false,
|
||||||
instanceNameInSearch: '',
|
instanceNameInSearch: '',
|
||||||
instanceThemes: {},
|
instanceThemes: {},
|
||||||
|
instanceSettings: {},
|
||||||
loggedInInstances: {},
|
loggedInInstances: {},
|
||||||
loggedInInstancesInOrder: [],
|
loggedInInstancesInOrder: [],
|
||||||
markMediaAsSensitive: false,
|
markMediaAsSensitive: false,
|
||||||
|
|
|
@ -2,8 +2,9 @@ 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 DEFAULT_LIGHT_THEME = 'default'
|
export const INLINE_THEME = 'default' // theme that does not require external CSS
|
||||||
export const DEFAULT_DARK_THEME = 'ozark'
|
export const DEFAULT_LIGHT_THEME = 'default' // theme that is shown by default
|
||||||
|
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 () {
|
||||||
|
@ -38,7 +39,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 !== DEFAULT_LIGHT_THEME) {
|
if (themeName !== INLINE_THEME) {
|
||||||
loadCSS(`/theme-${themeName}.css`)
|
loadCSS(`/theme-${themeName}.css`)
|
||||||
} else {
|
} else {
|
||||||
resetExistingTheme()
|
resetExistingTheme()
|
||||||
|
|
|
@ -131,78 +131,61 @@ async function showSimpleNotification (data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showRichNotification (data, notification) {
|
async function showRichNotification (data, notification) {
|
||||||
const { origin } = new URL(data.icon)
|
const { icon, body } = data
|
||||||
|
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: data.icon,
|
icon,
|
||||||
body: data.body,
|
body,
|
||||||
tag: notification.id,
|
tag,
|
||||||
data: {
|
data: {
|
||||||
url: `${self.location.origin}/accounts/${notification.account.id}`
|
url: `${origin}/accounts/${notification.account.id}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'mention': {
|
case 'reblog':
|
||||||
const actions = [{
|
case 'favourite':
|
||||||
action: 'favourite',
|
case 'poll':
|
||||||
title: 'Favourite'
|
await self.registration.showNotification(data.title, {
|
||||||
}]
|
icon,
|
||||||
|
body,
|
||||||
if ('reply' in NotificationEvent.prototype) {
|
tag,
|
||||||
actions.splice(0, 0, {
|
data: {
|
||||||
action: 'reply',
|
url: `${origin}/statuses/${notification.status.id}`
|
||||||
type: 'text',
|
|
||||||
title: 'Reply'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
if (['public', 'unlisted'].includes(notification.status.visibility)) {
|
break
|
||||||
actions.push({
|
case 'mention':
|
||||||
|
const isPublic = ['public', 'unlisted'].includes(notification.status.visibility)
|
||||||
|
const actions = [
|
||||||
|
{
|
||||||
|
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: data.icon,
|
icon,
|
||||||
body: data.body,
|
body,
|
||||||
tag: notification.id,
|
tag,
|
||||||
data: {
|
data: {
|
||||||
instance: origin,
|
instance: new URL(data.icon).origin,
|
||||||
status_id: notification.status.id,
|
status_id: notification.status.id,
|
||||||
access_token: data.access_token,
|
access_token: data.access_token,
|
||||||
url: `${self.location.origin}/statuses/${notification.status.id}`
|
url: `${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 => {
|
||||||
|
@ -210,8 +193,10 @@ const cloneNotification = notification => {
|
||||||
|
|
||||||
// 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
|
||||||
}
|
}
|
||||||
|
@ -227,21 +212,19 @@ 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': {
|
||||||
await post(`${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/reblog`, null, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
|
const url = `${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/reblog`
|
||||||
|
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': {
|
||||||
await post(`${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/favourite`, null, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
|
const url = `${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/favourite`
|
||||||
|
await post(url, null, {
|
||||||
|
'Authorization': `Bearer ${event.notification.data.access_token}`
|
||||||
|
})
|
||||||
await updateNotificationWithoutAction(event.notification, 'favourite')
|
await updateNotificationWithoutAction(event.notification, 'favourite')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before 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, notificationFiltersAll, notificationFiltersMention,
|
getUrl, notificationsTabAll, notificationsTabMentions,
|
||||||
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-filters.js`
|
fixture`033-notification-mentions.js`
|
||||||
.page`http://localhost:4002`
|
.page`http://localhost:4002`
|
||||||
|
|
||||||
test('Shows notification filters', async t => {
|
test('Shows notification mentions', 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(notificationFiltersMention)
|
.click(notificationsTabMentions)
|
||||||
.expect(getUrl()).match(/\/notifications\/mentions$/)
|
.expect(getUrl()).match(/\/notifications\/mentions$/)
|
||||||
await validateTimeline(t, notificationsMentions)
|
await validateTimeline(t, notificationsMentions)
|
||||||
await t.click(notificationFiltersAll)
|
await t.click(notificationsTabAll)
|
||||||
.expect(getUrl()).match(/\/notifications$/)
|
.expect(getUrl()).match(/\/notifications$/)
|
||||||
await validateTimeline(t, notifications)
|
await validateTimeline(t, notifications)
|
||||||
})
|
})
|
|
@ -0,0 +1,23 @@
|
||||||
|
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'
|
||||||
|
}))
|
||||||
|
})
|
|
@ -0,0 +1,48 @@
|
||||||
|
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, notificationFiltersAll, notificationFiltersMention,
|
getUrl, notificationsTabAll, notificationsTabMentions,
|
||||||
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-filters.js`
|
fixture`123-notification-mentions.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(notificationFiltersMention)
|
.click(notificationsTabMentions)
|
||||||
.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(notificationFiltersAll)
|
.click(notificationsTabAll)
|
||||||
.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(notificationFiltersMention)
|
.click(notificationsTabMentions)
|
||||||
.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(notificationFiltersAll)
|
.click(notificationsTabAll)
|
||||||
.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')
|
|
@ -0,0 +1,29 @@
|
||||||
|
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,8 +64,14 @@ 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 notificationFiltersAll = $('.notification-filters li:nth-child(1)')
|
export const notificationsTabAll = $('.notification-filters li:nth-child(1)')
|
||||||
export const notificationFiltersMention = $('.notification-filters li:nth-child(2)')
|
export const notificationsTabMentions = $('.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`)
|
||||||
|
|
141
yarn.lock
141
yarn.lock
|
@ -642,13 +642,15 @@ assert@^1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
util "0.10.3"
|
util "0.10.3"
|
||||||
|
|
||||||
assert@^1.5.0:
|
assert@^2.0.0:
|
||||||
version "1.5.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
|
resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32"
|
||||||
integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
|
integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==
|
||||||
dependencies:
|
dependencies:
|
||||||
object-assign "^4.1.1"
|
es6-object-assign "^1.1.0"
|
||||||
util "0.10.3"
|
is-nan "^1.2.1"
|
||||||
|
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"
|
||||||
|
@ -2031,6 +2033,11 @@ 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"
|
||||||
|
@ -2452,7 +2459,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.2, define-properties@^1.1.3:
|
define-properties@^1.1.1, 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==
|
||||||
|
@ -2798,6 +2805,11 @@ 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"
|
||||||
|
@ -2960,10 +2972,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.22:
|
esm@^3.2.25:
|
||||||
version "3.2.22"
|
version "3.2.25"
|
||||||
resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.22.tgz#5062c2e22fee3ccfee4e8f20da768330da90d6e3"
|
resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
|
||||||
integrity sha512-z8YG7U44L82j1XrdEJcqZOLUnjxco8pO453gKOlaMD1/md1n/5QrscAmYG+oKUspsmDLuBFZrpbxI6aQ67yRxA==
|
integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
|
||||||
|
|
||||||
esotope-hammerhead@^0.2.1:
|
esotope-hammerhead@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
|
@ -4008,6 +4020,11 @@ 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"
|
||||||
|
@ -4144,6 +4161,11 @@ 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"
|
||||||
|
@ -4177,6 +4199,13 @@ 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"
|
||||||
|
@ -4286,10 +4315,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.0.0:
|
jest-worker@^24.6.0:
|
||||||
version "24.0.0"
|
version "24.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d"
|
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3"
|
||||||
integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg==
|
integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
merge-stream "^1.0.1"
|
merge-stream "^1.0.1"
|
||||||
supports-color "^6.1.0"
|
supports-color "^6.1.0"
|
||||||
|
@ -5246,6 +5275,11 @@ 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"
|
||||||
|
@ -5273,6 +5307,16 @@ 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"
|
||||||
|
@ -6352,15 +6396,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@^4.0.4:
|
rollup-plugin-terser@^5.0.0:
|
||||||
version "4.0.4"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-4.0.4.tgz#6f661ef284fa7c27963d242601691dc3d23f994e"
|
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.0.0.tgz#ac50fdb703b580447a7e6b1692aeed515a6be8cf"
|
||||||
integrity sha512-wPANT5XKVJJ8RDUN0+wIr7UPd0lIXBo4UdJ59VmlPCtlFsE20AM+14pe+tk7YunCsWEiuzkDBY3QIkSCjtrPXg==
|
integrity sha512-W+jJ4opYnlmNyVW0vtRufs+EGf68BIJ7bnOazgz8mgz8pA9lUyrEifAhPs5y9M16wFeAyBGaRjKip4dnFBtXaw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.0.0"
|
"@babel/code-frame" "^7.0.0"
|
||||||
jest-worker "^24.0.0"
|
jest-worker "^24.6.0"
|
||||||
serialize-javascript "^1.6.1"
|
serialize-javascript "^1.7.0"
|
||||||
terser "^3.14.1"
|
terser "^4.0.0"
|
||||||
|
|
||||||
rollup-pluginutils@^2.6.0:
|
rollup-pluginutils@^2.6.0:
|
||||||
version "2.6.0"
|
version "2.6.0"
|
||||||
|
@ -6512,11 +6556,16 @@ 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.6.1:
|
serialize-javascript@^1.4.0:
|
||||||
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"
|
||||||
|
@ -6675,6 +6724,14 @@ 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"
|
||||||
|
@ -7149,15 +7206,6 @@ 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.14.1, terser@^3.8.1:
|
|
||||||
version "3.14.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32"
|
|
||||||
integrity sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw==
|
|
||||||
dependencies:
|
|
||||||
commander "~2.17.1"
|
|
||||||
source-map "~0.6.1"
|
|
||||||
source-map-support "~0.5.6"
|
|
||||||
|
|
||||||
terser@^3.16.1:
|
terser@^3.16.1:
|
||||||
version "3.16.1"
|
version "3.16.1"
|
||||||
resolved "https://registry.yarnpkg.com/terser/-/terser-3.16.1.tgz#5b0dd4fa1ffd0b0b43c2493b2c364fd179160493"
|
resolved "https://registry.yarnpkg.com/terser/-/terser-3.16.1.tgz#5b0dd4fa1ffd0b0b43c2493b2c364fd179160493"
|
||||||
|
@ -7167,6 +7215,24 @@ terser@^3.16.1:
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
source-map-support "~0.5.9"
|
source-map-support "~0.5.9"
|
||||||
|
|
||||||
|
terser@^3.8.1:
|
||||||
|
version "3.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32"
|
||||||
|
integrity sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw==
|
||||||
|
dependencies:
|
||||||
|
commander "~2.17.1"
|
||||||
|
source-map "~0.6.1"
|
||||||
|
source-map-support "~0.5.6"
|
||||||
|
|
||||||
|
terser@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.0.tgz#ef356f6f359a963e2cc675517f21c1c382877374"
|
||||||
|
integrity sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA==
|
||||||
|
dependencies:
|
||||||
|
commander "^2.19.0"
|
||||||
|
source-map "~0.6.1"
|
||||||
|
source-map-support "~0.5.10"
|
||||||
|
|
||||||
testcafe-browser-tools@1.6.8:
|
testcafe-browser-tools@1.6.8:
|
||||||
version "1.6.8"
|
version "1.6.8"
|
||||||
resolved "https://registry.yarnpkg.com/testcafe-browser-tools/-/testcafe-browser-tools-1.6.8.tgz#74ace1ee4c21a20bd6d88238f0d9bc97c596b8fb"
|
resolved "https://registry.yarnpkg.com/testcafe-browser-tools/-/testcafe-browser-tools-1.6.8.tgz#74ace1ee4c21a20bd6d88238f0d9bc97c596b8fb"
|
||||||
|
@ -7714,6 +7780,17 @@ 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…
Reference in New Issue