Merge branch 'develop' into 'iss-149/profile-fields-setting'
# Conflicts: # src/components/settings_modal/tabs/profile_tab.vue
This commit is contained in:
commit
ea0a12f604
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -4,28 +4,38 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Changed
|
### Changed
|
||||||
|
- Greentext now has separate color slot for it
|
||||||
- Removed the use of with_move parameters when fetching notifications
|
- Removed the use of with_move parameters when fetching notifications
|
||||||
|
- Push notifications now are the same as normal notfication, and are localized.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- Weird bug related to post being sent seemingly after pasting with keyboard (hopefully)
|
||||||
- Multiple issues with muted statuses/notifications
|
- Multiple issues with muted statuses/notifications
|
||||||
|
|
||||||
## [Unreleased patch]
|
## [Unreleased patch]
|
||||||
### Add
|
### Add
|
||||||
- Added private notifications option for push notifications
|
- Added private notifications option for push notifications
|
||||||
- 'Copy link' button for statuses (in the ellipsis menu)
|
- 'Copy link' button for statuses (in the ellipsis menu)
|
||||||
|
- Autocomplete domains from list of known instances
|
||||||
|
- 'Bot' settings option and badge
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Registration page no longer requires email if the server is configured not to require it
|
- Registration page no longer requires email if the server is configured not to require it
|
||||||
- Change heart to thumbs up in reaction picker
|
- Change heart to thumbs up in reaction picker
|
||||||
- Close the media modal on navigation events
|
- Close the media modal on navigation events
|
||||||
- Add colons to the emoji alt text, to make them copyable
|
- Add colons to the emoji alt text, to make them copyable
|
||||||
|
- Add better visual indication for drag-and-drop for files
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- Custom Emoji will display in poll options now.
|
||||||
- Status ellipsis menu closes properly when selecting certain options
|
- Status ellipsis menu closes properly when selecting certain options
|
||||||
- Cropped images look correct in Chrome
|
- Cropped images look correct in Chrome
|
||||||
- Newlines in the muted words settings work again
|
- Newlines in the muted words settings work again
|
||||||
- Clicking on non-latin hashtags won't open a new window
|
- Clicking on non-latin hashtags won't open a new window
|
||||||
- Uploading and drag-dropping multiple files works correctly now.
|
- Uploading and drag-dropping multiple files works correctly now.
|
||||||
|
- Subject field now appears disabled when posting
|
||||||
|
- Fix status ellipsis menu being cut off in notifications column
|
||||||
|
- Fixed autocomplete sometimes not returning the right user when there's already some results
|
||||||
|
|
||||||
## [2.0.3] - 2020-05-02
|
## [2.0.3] - 2020-05-02
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -22,12 +22,9 @@
|
||||||
"cropperjs": "^1.4.3",
|
"cropperjs": "^1.4.3",
|
||||||
"diff": "^3.0.1",
|
"diff": "^3.0.1",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
"karma-mocha-reporter": "^2.2.1",
|
|
||||||
"localforage": "^1.5.0",
|
"localforage": "^1.5.0",
|
||||||
"object-path": "^0.11.3",
|
|
||||||
"phoenix": "^1.3.0",
|
"phoenix": "^1.3.0",
|
||||||
"portal-vue": "^2.1.4",
|
"portal-vue": "^2.1.4",
|
||||||
"sanitize-html": "^1.13.0",
|
|
||||||
"v-click-outside": "^2.1.1",
|
"v-click-outside": "^2.1.1",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-chat-scroll": "^1.2.1",
|
"vue-chat-scroll": "^1.2.1",
|
||||||
|
@ -35,10 +32,10 @@
|
||||||
"vue-router": "^3.0.1",
|
"vue-router": "^3.0.1",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"vue-template-compiler": "^2.6.11",
|
||||||
"vuelidate": "^0.7.4",
|
"vuelidate": "^0.7.4",
|
||||||
"vuex": "^3.0.1",
|
"vuex": "^3.0.1"
|
||||||
"whatwg-fetch": "^2.0.3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"karma-mocha-reporter": "^2.2.1",
|
||||||
"@babel/core": "^7.7.5",
|
"@babel/core": "^7.7.5",
|
||||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||||
"@babel/preset-env": "^7.7.6",
|
"@babel/preset-env": "^7.7.6",
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<Popover
|
<Popover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
|
:bound-to="{ x: 'container' }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
slot="content"
|
slot="content"
|
||||||
|
|
|
@ -5,9 +5,20 @@ const DomainMuteCard = {
|
||||||
components: {
|
components: {
|
||||||
ProgressButton
|
ProgressButton
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
muted () {
|
||||||
|
return this.user.domainMutes.includes(this.domain)
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unmuteDomain () {
|
unmuteDomain () {
|
||||||
return this.$store.dispatch('unmuteDomain', this.domain)
|
return this.$store.dispatch('unmuteDomain', this.domain)
|
||||||
|
},
|
||||||
|
muteDomain () {
|
||||||
|
return this.$store.dispatch('muteDomain', this.domain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
</div>
|
</div>
|
||||||
<ProgressButton
|
<ProgressButton
|
||||||
|
v-if="muted"
|
||||||
:click="unmuteDomain"
|
:click="unmuteDomain"
|
||||||
class="btn btn-default"
|
class="btn btn-default"
|
||||||
>
|
>
|
||||||
|
@ -12,6 +13,16 @@
|
||||||
{{ $t('domain_mute_card.unmute_progress') }}
|
{{ $t('domain_mute_card.unmute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
|
<ProgressButton
|
||||||
|
v-else
|
||||||
|
:click="muteDomain"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('domain_mute_card.mute') }}
|
||||||
|
<template slot="progress">
|
||||||
|
{{ $t('domain_mute_card.mute_progress') }}
|
||||||
|
</template>
|
||||||
|
</ProgressButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -34,5 +45,9 @@
|
||||||
button {
|
button {
|
||||||
width: 10em;
|
width: 10em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.autosuggest-results & {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { debounce } from 'lodash'
|
||||||
|
|
||||||
const debounceUserSearch = debounce((data, input) => {
|
const debounceUserSearch = debounce((data, input) => {
|
||||||
data.updateUsersList(input)
|
data.updateUsersList(input)
|
||||||
}, 500, { leading: true, trailing: false })
|
}, 500)
|
||||||
|
|
||||||
export default data => input => {
|
export default data => input => {
|
||||||
const firstChar = input[0]
|
const firstChar = input[0]
|
||||||
|
@ -97,8 +97,8 @@ export const suggestUsers = data => input => {
|
||||||
replacement: '@' + screen_name + ' '
|
replacement: '@' + screen_name + ' '
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// BE search users if there are no matches
|
// BE search users to get more comprehensive results
|
||||||
if (newUsers.length === 0 && data.updateUsersList) {
|
if (data.updateUsersList) {
|
||||||
debounceUserSearch(data, noPrefix)
|
debounceUserSearch(data, noPrefix)
|
||||||
}
|
}
|
||||||
return newUsers
|
return newUsers
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
trigger="click"
|
trigger="click"
|
||||||
placement="top"
|
placement="top"
|
||||||
class="extra-button-popover"
|
class="extra-button-popover"
|
||||||
|
:bound-to="{ x: 'container' }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
slot="content"
|
slot="content"
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
video,
|
video,
|
||||||
canvas {
|
canvas {
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,20 +45,6 @@ const mediaUpload = {
|
||||||
this.$emit('all-uploaded')
|
this.$emit('all-uploaded')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fileDrop (e) {
|
|
||||||
if (e.dataTransfer.files.length > 0) {
|
|
||||||
e.preventDefault() // allow dropping text like before
|
|
||||||
this.multiUpload(e.dataTransfer.files)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fileDrag (e) {
|
|
||||||
let types = e.dataTransfer.types
|
|
||||||
if (types.contains('Files')) {
|
|
||||||
e.dataTransfer.dropEffect = 'copy'
|
|
||||||
} else {
|
|
||||||
e.dataTransfer.dropEffect = 'none'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clearFile () {
|
clearFile () {
|
||||||
this.uploadReady = false
|
this.uploadReady = false
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="media-upload">
|
||||||
class="media-upload"
|
|
||||||
@drop.prevent
|
|
||||||
@dragover.prevent="fileDrag"
|
|
||||||
@drop="fileDrop"
|
|
||||||
>
|
|
||||||
<label
|
<label
|
||||||
class="label"
|
class="label"
|
||||||
:title="$t('tool_tip.media_upload')"
|
:title="$t('tool_tip.media_upload')"
|
||||||
|
|
|
@ -54,25 +54,20 @@
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
padding: 0.6em;
|
padding: 0.6em;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
.avatar-container {
|
.avatar-container {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
.status-el {
|
|
||||||
.status {
|
.status-body {
|
||||||
padding: 0.25em 0;
|
color: $fallback--faint;
|
||||||
color: $fallback--faint;
|
color: var(--faint, $fallback--faint);
|
||||||
color: var(--faint, $fallback--faint);
|
a {
|
||||||
a {
|
color: var(--faintLink);
|
||||||
color: var(--faintLink);
|
|
||||||
}
|
|
||||||
.status-content a {
|
|
||||||
color: var(--postFaintLink);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
padding: 0;
|
.status-content a {
|
||||||
.media-body {
|
color: var(--postFaintLink);
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<span class="result-percentage">
|
<span class="result-percentage">
|
||||||
{{ percentageForOption(option.votes_count) }}%
|
{{ percentageForOption(option.votes_count) }}%
|
||||||
</span>
|
</span>
|
||||||
<span>{{ option.title }}</span>
|
<span v-html="option.title_html"></span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="result-fill"
|
class="result-fill"
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
const Popover = {
|
const Popover = {
|
||||||
name: 'Popover',
|
name: 'Popover',
|
||||||
props: {
|
props: {
|
||||||
|
@ -10,6 +9,9 @@ const Popover = {
|
||||||
// 'container' for using offsetParent as boundaries for either axis
|
// 'container' for using offsetParent as boundaries for either axis
|
||||||
// or 'viewport'
|
// or 'viewport'
|
||||||
boundTo: Object,
|
boundTo: Object,
|
||||||
|
// Takes a selector to use as a replacement for the parent container
|
||||||
|
// for getting boundaries for x an y axis
|
||||||
|
boundToSelector: String,
|
||||||
// Takes a top/bottom/left/right object, how much space to leave
|
// Takes a top/bottom/left/right object, how much space to leave
|
||||||
// between boundary and popover element
|
// between boundary and popover element
|
||||||
margin: Object,
|
margin: Object,
|
||||||
|
@ -27,6 +29,10 @@ const Popover = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
containerBoundingClientRect () {
|
||||||
|
const container = this.boundToSelector ? this.$el.closest(this.boundToSelector) : this.$el.offsetParent
|
||||||
|
return container.getBoundingClientRect()
|
||||||
|
},
|
||||||
updateStyles () {
|
updateStyles () {
|
||||||
if (this.hidden) {
|
if (this.hidden) {
|
||||||
this.styles = {
|
this.styles = {
|
||||||
|
@ -45,7 +51,8 @@ const Popover = {
|
||||||
// Minor optimization, don't call a slow reflow call if we don't have to
|
// Minor optimization, don't call a slow reflow call if we don't have to
|
||||||
const parentBounds = this.boundTo &&
|
const parentBounds = this.boundTo &&
|
||||||
(this.boundTo.x === 'container' || this.boundTo.y === 'container') &&
|
(this.boundTo.x === 'container' || this.boundTo.y === 'container') &&
|
||||||
this.$el.offsetParent.getBoundingClientRect()
|
this.containerBoundingClientRect()
|
||||||
|
|
||||||
const margin = this.margin || {}
|
const margin = this.margin || {}
|
||||||
|
|
||||||
// What are the screen bounds for the popover? Viewport vs container
|
// What are the screen bounds for the popover? Viewport vs container
|
||||||
|
|
|
@ -82,7 +82,9 @@ const PostStatusForm = {
|
||||||
contentType
|
contentType
|
||||||
},
|
},
|
||||||
caret: 0,
|
caret: 0,
|
||||||
pollFormVisible: false
|
pollFormVisible: false,
|
||||||
|
showDropIcon: 'hide',
|
||||||
|
dropStopTimeout: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -248,13 +250,27 @@ const PostStatusForm = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fileDrop (e) {
|
fileDrop (e) {
|
||||||
if (e.dataTransfer.files.length > 0) {
|
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
|
||||||
e.preventDefault() // allow dropping text like before
|
e.preventDefault() // allow dropping text like before
|
||||||
this.dropFiles = e.dataTransfer.files
|
this.dropFiles = e.dataTransfer.files
|
||||||
|
clearTimeout(this.dropStopTimeout)
|
||||||
|
this.showDropIcon = 'hide'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
fileDragStop (e) {
|
||||||
|
// The false-setting is done with delay because just using leave-events
|
||||||
|
// directly caused unwanted flickering, this is not perfect either but
|
||||||
|
// much less noticable.
|
||||||
|
clearTimeout(this.dropStopTimeout)
|
||||||
|
this.showDropIcon = 'fade'
|
||||||
|
this.dropStopTimeout = setTimeout(() => (this.showDropIcon = 'hide'), 500)
|
||||||
|
},
|
||||||
fileDrag (e) {
|
fileDrag (e) {
|
||||||
e.dataTransfer.dropEffect = 'copy'
|
e.dataTransfer.dropEffect = 'copy'
|
||||||
|
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
|
||||||
|
clearTimeout(this.dropStopTimeout)
|
||||||
|
this.showDropIcon = 'show'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onEmojiInputInput (e) {
|
onEmojiInputInput (e) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
|
@ -6,7 +6,15 @@
|
||||||
<form
|
<form
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@submit.prevent="postStatus(newStatus)"
|
@submit.prevent="postStatus(newStatus)"
|
||||||
|
@dragover.prevent="fileDrag"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
v-show="showDropIcon !== 'hide'"
|
||||||
|
:style="{ animation: showDropIcon === 'show' ? 'fade-in 0.25s' : 'fade-out 0.5s' }"
|
||||||
|
class="drop-indicator icon-upload"
|
||||||
|
@dragleave="fileDragStop"
|
||||||
|
@drop.stop="fileDrop"
|
||||||
|
/>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<i18n
|
<i18n
|
||||||
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
|
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
|
||||||
|
@ -73,6 +81,7 @@
|
||||||
v-model="newStatus.spoilerText"
|
v-model="newStatus.spoilerText"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('post_status.content_warning')"
|
:placeholder="$t('post_status.content_warning')"
|
||||||
|
:disabled="posting"
|
||||||
class="form-post-subject"
|
class="form-post-subject"
|
||||||
>
|
>
|
||||||
</EmojiInput>
|
</EmojiInput>
|
||||||
|
@ -96,9 +105,7 @@
|
||||||
:disabled="posting"
|
:disabled="posting"
|
||||||
class="form-post-body"
|
class="form-post-body"
|
||||||
@keydown.meta.enter="postStatus(newStatus)"
|
@keydown.meta.enter="postStatus(newStatus)"
|
||||||
@keyup.ctrl.enter="postStatus(newStatus)"
|
@keydown.ctrl.enter="postStatus(newStatus)"
|
||||||
@drop="fileDrop"
|
|
||||||
@dragover.prevent="fileDrag"
|
|
||||||
@input="resize"
|
@input="resize"
|
||||||
@compositionupdate="resize"
|
@compositionupdate="resize"
|
||||||
@paste="paste"
|
@paste="paste"
|
||||||
|
@ -447,7 +454,8 @@
|
||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 0.6em;
|
margin: 0.6em;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
.form-group {
|
||||||
|
@ -505,5 +513,35 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 0.6; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-out {
|
||||||
|
from { opacity: 0.6; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-indicator {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 5em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0.6;
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
background-color: $fallback--bg;
|
||||||
|
background-color: var(--bg, $fallback--bg);
|
||||||
|
border-radius: $fallback--tooltipRadius;
|
||||||
|
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
|
||||||
|
border: 2px dashed $fallback--text;
|
||||||
|
border: 2px dashed var(--text, $fallback--text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,6 +13,9 @@ const PostStatusModal = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
isLoggedIn () {
|
||||||
|
return !!this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
modalActivated () {
|
modalActivated () {
|
||||||
return this.$store.state.postStatus.modalActivated
|
return this.$store.state.postStatus.modalActivated
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<Modal
|
<Modal
|
||||||
|
v-if="isLoggedIn && !resettingForm"
|
||||||
:is-open="modalActivated"
|
:is-open="modalActivated"
|
||||||
class="post-form-modal-view"
|
class="post-form-modal-view"
|
||||||
@backdropClicked="closeModal"
|
@backdropClicked="closeModal"
|
||||||
|
|
|
@ -32,12 +32,12 @@ const DomainMuteList = withSubscription({
|
||||||
const MutesAndBlocks = {
|
const MutesAndBlocks = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
activeTab: 'profile',
|
activeTab: 'profile'
|
||||||
newDomainToMute: ''
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.$store.dispatch('fetchTokens')
|
this.$store.dispatch('fetchTokens')
|
||||||
|
this.$store.dispatch('getKnownDomains')
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
TabSwitcher,
|
TabSwitcher,
|
||||||
|
@ -51,6 +51,14 @@ const MutesAndBlocks = {
|
||||||
Autosuggest,
|
Autosuggest,
|
||||||
Checkbox
|
Checkbox
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
knownDomains () {
|
||||||
|
return this.$store.state.instance.knownDomains
|
||||||
|
},
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
importFollows (file) {
|
importFollows (file) {
|
||||||
return this.$store.state.api.backendInteractor.importFollows({ file })
|
return this.$store.state.api.backendInteractor.importFollows({ file })
|
||||||
|
@ -86,13 +94,13 @@ const MutesAndBlocks = {
|
||||||
filterUnblockedUsers (userIds) {
|
filterUnblockedUsers (userIds) {
|
||||||
return reject(userIds, (userId) => {
|
return reject(userIds, (userId) => {
|
||||||
const relationship = this.$store.getters.relationship(this.userId)
|
const relationship = this.$store.getters.relationship(this.userId)
|
||||||
return relationship.blocking || userId === this.$store.state.users.currentUser.id
|
return relationship.blocking || userId === this.user.id
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
filterUnMutedUsers (userIds) {
|
filterUnMutedUsers (userIds) {
|
||||||
return reject(userIds, (userId) => {
|
return reject(userIds, (userId) => {
|
||||||
const relationship = this.$store.getters.relationship(this.userId)
|
const relationship = this.$store.getters.relationship(this.userId)
|
||||||
return relationship.muting || userId === this.$store.state.users.currentUser.id
|
return relationship.muting || userId === this.user.id
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
queryUserIds (query) {
|
queryUserIds (query) {
|
||||||
|
@ -111,12 +119,16 @@ const MutesAndBlocks = {
|
||||||
unmuteUsers (ids) {
|
unmuteUsers (ids) {
|
||||||
return this.$store.dispatch('unmuteUsers', ids)
|
return this.$store.dispatch('unmuteUsers', ids)
|
||||||
},
|
},
|
||||||
|
filterUnMutedDomains (urls) {
|
||||||
|
return urls.filter(url => !this.user.domainMutes.includes(url))
|
||||||
|
},
|
||||||
|
queryKnownDomains (query) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve(this.knownDomains.filter(url => url.toLowerCase().includes(query)))
|
||||||
|
})
|
||||||
|
},
|
||||||
unmuteDomains (domains) {
|
unmuteDomains (domains) {
|
||||||
return this.$store.dispatch('unmuteDomains', domains)
|
return this.$store.dispatch('unmuteDomains', domains)
|
||||||
},
|
|
||||||
muteDomain () {
|
|
||||||
return this.$store.dispatch('muteDomain', this.newDomainToMute)
|
|
||||||
.then(() => { this.newDomainToMute = '' })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,21 +119,16 @@
|
||||||
|
|
||||||
<div :label="$t('settings.domain_mutes')">
|
<div :label="$t('settings.domain_mutes')">
|
||||||
<div class="domain-mute-form">
|
<div class="domain-mute-form">
|
||||||
<input
|
<Autosuggest
|
||||||
v-model="newDomainToMute"
|
:filter="filterUnMutedDomains"
|
||||||
|
:query="queryKnownDomains"
|
||||||
:placeholder="$t('settings.type_domains_to_mute')"
|
:placeholder="$t('settings.type_domains_to_mute')"
|
||||||
type="text"
|
|
||||||
@keyup.enter="muteDomain"
|
|
||||||
>
|
>
|
||||||
<ProgressButton
|
<DomainMuteCard
|
||||||
class="btn btn-default domain-mute-button"
|
slot-scope="row"
|
||||||
:click="muteDomain"
|
:domain="row.item"
|
||||||
>
|
/>
|
||||||
{{ $t('domain_mute_card.mute') }}
|
</Autosuggest>
|
||||||
<template slot="progress">
|
|
||||||
{{ $t('domain_mute_card.mute_progress') }}
|
|
||||||
</template>
|
|
||||||
</ProgressButton>
|
|
||||||
</div>
|
</div>
|
||||||
<DomainMuteList
|
<DomainMuteList
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
|
|
|
@ -25,6 +25,7 @@ const ProfileTab = {
|
||||||
showRole: this.$store.state.users.currentUser.show_role,
|
showRole: this.$store.state.users.currentUser.show_role,
|
||||||
role: this.$store.state.users.currentUser.role,
|
role: this.$store.state.users.currentUser.role,
|
||||||
discoverable: this.$store.state.users.currentUser.discoverable,
|
discoverable: this.$store.state.users.currentUser.discoverable,
|
||||||
|
bot: this.$store.state.users.currentUser.bot,
|
||||||
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
|
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
|
||||||
pickAvatarBtnVisible: true,
|
pickAvatarBtnVisible: true,
|
||||||
bannerUploading: false,
|
bannerUploading: false,
|
||||||
|
@ -94,6 +95,7 @@ const ProfileTab = {
|
||||||
hide_follows: this.hideFollows,
|
hide_follows: this.hideFollows,
|
||||||
hide_followers: this.hideFollowers,
|
hide_followers: this.hideFollowers,
|
||||||
discoverable: this.discoverable,
|
discoverable: this.discoverable,
|
||||||
|
bot: this.bot,
|
||||||
allow_following_move: this.allowFollowingMove,
|
allow_following_move: this.allowFollowingMove,
|
||||||
hide_follows_count: this.hideFollowsCount,
|
hide_follows_count: this.hideFollowsCount,
|
||||||
hide_followers_count: this.hideFollowersCount,
|
hide_followers_count: this.hideFollowersCount,
|
||||||
|
|
|
@ -143,6 +143,11 @@
|
||||||
{{ $t("settings.profile_fields.add_field") }}
|
{{ $t("settings.profile_fields.add_field") }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="bot">
|
||||||
|
{{ $t('settings.bot') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
<button
|
<button
|
||||||
:disabled="newName && newName.length === 0"
|
:disabled="newName && newName.length === 0"
|
||||||
class="btn btn-default"
|
class="btn btn-default"
|
||||||
|
|
|
@ -256,6 +256,13 @@
|
||||||
:label="$t('settings.links')"
|
:label="$t('settings.links')"
|
||||||
/>
|
/>
|
||||||
<ContrastRatio :contrast="previewContrast.postLink" />
|
<ContrastRatio :contrast="previewContrast.postLink" />
|
||||||
|
<ColorInput
|
||||||
|
v-model="postGreentextColorLocal"
|
||||||
|
name="postGreentextColor"
|
||||||
|
:fallback="previewTheme.colors.cGreen"
|
||||||
|
:label="$t('settings.greentext')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.postGreentext" />
|
||||||
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
|
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
|
||||||
<ColorInput
|
<ColorInput
|
||||||
v-model="alertErrorColorLocal"
|
v-model="alertErrorColorLocal"
|
||||||
|
|
|
@ -418,7 +418,7 @@ $status-margin: 0.75em;
|
||||||
max-width: 85%;
|
max-width: 85%;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
img {
|
img.emoji {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
|
@ -164,23 +164,23 @@ $status-margin: 0.75em;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img, video {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 400px;
|
||||||
|
vertical-align: middle;
|
||||||
|
object-fit: contain;
|
||||||
|
|
||||||
|
&.emoji {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.status-content {
|
.status-content {
|
||||||
font-family: var(--postFont, sans-serif);
|
font-family: var(--postFont, sans-serif);
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
|
||||||
img, video {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 400px;
|
|
||||||
vertical-align: middle;
|
|
||||||
object-fit: contain;
|
|
||||||
|
|
||||||
&.emoji {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
margin: 0.2em 0 0.2em 2em;
|
margin: 0.2em 0 0.2em 2em;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
@ -226,7 +226,7 @@ $status-margin: 0.75em;
|
||||||
|
|
||||||
.greentext {
|
.greentext {
|
||||||
color: $fallback--cGreen;
|
color: $fallback--cGreen;
|
||||||
color: var(--cGreen, $fallback--cGreen);
|
color: var(--postGreentext, $fallback--cGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline :not(.panel-disabled) > {
|
.timeline :not(.panel-disabled) > {
|
||||||
|
|
|
@ -23,13 +23,6 @@
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
@import '../../_variables.scss';
|
||||||
.contain-fit {
|
|
||||||
.still-image {
|
|
||||||
img {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.still-image {
|
.still-image {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -38,6 +31,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
&:hover canvas {
|
&:hover canvas {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -45,8 +39,8 @@
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
align-self: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.animated {
|
&.animated {
|
||||||
|
|
|
@ -70,10 +70,20 @@
|
||||||
>
|
>
|
||||||
@{{ user.screen_name }}
|
@{{ user.screen_name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
<span
|
<template v-if="!hideBio">
|
||||||
v-if="!hideBio && !!visibleRole"
|
<span
|
||||||
class="alert staff"
|
v-if="!!visibleRole"
|
||||||
>{{ visibleRole }}</span>
|
class="alert user-role"
|
||||||
|
>
|
||||||
|
{{ visibleRole }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="user.bot"
|
||||||
|
class="alert user-role"
|
||||||
|
>
|
||||||
|
bot
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<span v-if="user.locked"><i class="icon icon-lock" /></span>
|
<span v-if="user.locked"><i class="icon icon-lock" /></span>
|
||||||
<span
|
<span
|
||||||
v-if="!mergedConfig.hideUserStats && !hideBio"
|
v-if="!mergedConfig.hideUserStats && !hideBio"
|
||||||
|
@ -458,7 +468,7 @@
|
||||||
color: var(--text, $fallback--text);
|
color: var(--text, $fallback--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.staff {
|
.user-role {
|
||||||
flex: none;
|
flex: none;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
color: $fallback--text;
|
color: $fallback--text;
|
||||||
|
|
|
@ -124,6 +124,14 @@ const UserProfile = {
|
||||||
onTabSwitch (tab) {
|
onTabSwitch (tab) {
|
||||||
this.tab = tab
|
this.tab = tab
|
||||||
this.$router.replace({ query: { tab } })
|
this.$router.replace({ query: { tab } })
|
||||||
|
},
|
||||||
|
linkClicked ({ target }) {
|
||||||
|
if (target.tagName === 'SPAN') {
|
||||||
|
target = target.parentNode
|
||||||
|
}
|
||||||
|
if (target.tagName === 'A') {
|
||||||
|
window.open(target.href, '_blank')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
@ -11,6 +11,31 @@
|
||||||
:allow-zooming-avatar="true"
|
:allow-zooming-avatar="true"
|
||||||
rounded="top"
|
rounded="top"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
v-if="user.fields_html && user.fields_html.length > 0"
|
||||||
|
class="user-profile-fields"
|
||||||
|
>
|
||||||
|
<dl
|
||||||
|
v-for="(field, index) in user.fields_html"
|
||||||
|
:key="index"
|
||||||
|
class="user-profile-field"
|
||||||
|
>
|
||||||
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
<dt
|
||||||
|
:title="user.fields_text[index].name"
|
||||||
|
class="user-profile-field-name"
|
||||||
|
@click.prevent="linkClicked"
|
||||||
|
v-html="field.name"
|
||||||
|
/>
|
||||||
|
<dd
|
||||||
|
:title="user.fields_text[index].value"
|
||||||
|
class="user-profile-field-value"
|
||||||
|
@click.prevent="linkClicked"
|
||||||
|
v-html="field.value"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
<tab-switcher
|
<tab-switcher
|
||||||
:active-tab="tab"
|
:active-tab="tab"
|
||||||
:render-only-focused="true"
|
:render-only-focused="true"
|
||||||
|
@ -108,11 +133,60 @@
|
||||||
<script src="./user_profile.js"></script>
|
<script src="./user_profile.js"></script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
.user-profile {
|
.user-profile {
|
||||||
flex: 2;
|
flex: 2;
|
||||||
flex-basis: 500px;
|
flex-basis: 500px;
|
||||||
|
|
||||||
|
.user-profile-fields {
|
||||||
|
margin: 0 0.5em;
|
||||||
|
img {
|
||||||
|
object-fit: contain;
|
||||||
|
vertical-align: middle;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 400px;
|
||||||
|
|
||||||
|
&.emoji {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-field {
|
||||||
|
display: flex;
|
||||||
|
margin: 0.25em auto;
|
||||||
|
max-width: 32em;
|
||||||
|
border: 1px solid var(--border, $fallback--border);
|
||||||
|
border-radius: $fallback--inputRadius;
|
||||||
|
border-radius: var(--inputRadius, $fallback--inputRadius);
|
||||||
|
|
||||||
|
.user-profile-field-name {
|
||||||
|
flex: 0 1 30%;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--lightText);
|
||||||
|
min-width: 120px;
|
||||||
|
border-right: 1px solid var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-field-value {
|
||||||
|
flex: 1 1 70%;
|
||||||
|
color: var(--text);
|
||||||
|
margin: 0 0 0 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-field-name, .user-profile-field-value {
|
||||||
|
line-height: 18px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0.5em 1.5em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.userlist-placeholder {
|
.userlist-placeholder {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
@ -266,6 +266,7 @@
|
||||||
"block_import_error": "Error importing blocks",
|
"block_import_error": "Error importing blocks",
|
||||||
"blocks_imported": "Blocks imported! Processing them will take a while.",
|
"blocks_imported": "Blocks imported! Processing them will take a while.",
|
||||||
"blocks_tab": "Blocks",
|
"blocks_tab": "Blocks",
|
||||||
|
"bot": "This is a bot account",
|
||||||
"btnRadius": "Buttons",
|
"btnRadius": "Buttons",
|
||||||
"cBlue": "Blue (Reply, follow)",
|
"cBlue": "Blue (Reply, follow)",
|
||||||
"cGreen": "Green (Retweet)",
|
"cGreen": "Green (Retweet)",
|
||||||
|
@ -407,7 +408,7 @@
|
||||||
"theme_help_v2_1": "You can also override certain component's colors and opacity by toggling the checkbox, use \"Clear all\" button to clear all overrides.",
|
"theme_help_v2_1": "You can also override certain component's colors and opacity by toggling the checkbox, use \"Clear all\" button to clear all overrides.",
|
||||||
"theme_help_v2_2": "Icons underneath some entries are background/text contrast indicators, hover over for detailed info. Please keep in mind that when using transparency contrast indicators show the worst possible case.",
|
"theme_help_v2_2": "Icons underneath some entries are background/text contrast indicators, hover over for detailed info. Please keep in mind that when using transparency contrast indicators show the worst possible case.",
|
||||||
"tooltipRadius": "Tooltips/alerts",
|
"tooltipRadius": "Tooltips/alerts",
|
||||||
"type_domains_to_mute": "Type in domains to mute",
|
"type_domains_to_mute": "Search domains to mute",
|
||||||
"upload_a_photo": "Upload a photo",
|
"upload_a_photo": "Upload a photo",
|
||||||
"user_settings": "User Settings",
|
"user_settings": "User Settings",
|
||||||
"values": {
|
"values": {
|
||||||
|
|
|
@ -12,7 +12,12 @@
|
||||||
"disable": "Disabilita",
|
"disable": "Disabilita",
|
||||||
"enable": "Abilita",
|
"enable": "Abilita",
|
||||||
"confirm": "Conferma",
|
"confirm": "Conferma",
|
||||||
"verify": "Verifica"
|
"verify": "Verifica",
|
||||||
|
"peek": "Anteprima",
|
||||||
|
"close": "Chiudi",
|
||||||
|
"retry": "Riprova",
|
||||||
|
"error_retry": "Per favore, riprova",
|
||||||
|
"loading": "Carico…"
|
||||||
},
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"mentions": "Menzioni",
|
"mentions": "Menzioni",
|
||||||
|
@ -212,7 +217,63 @@
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"opacity": "Opacità",
|
"opacity": "Opacità",
|
||||||
"color": "Colore"
|
"color": "Colore",
|
||||||
|
"contrast": {
|
||||||
|
"context": {
|
||||||
|
"text": "per il testo",
|
||||||
|
"18pt": "per il testo grande (oltre 17pt)"
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"bad": "non soddisfa le linee guida di alcun livello",
|
||||||
|
"aaa": "soddisfa le linee guida di livello AAA (ottimo)",
|
||||||
|
"aa": "soddisfa le linee guida di livello AA (sufficiente)"
|
||||||
|
},
|
||||||
|
"hint": "Il rapporto di contrasto è {ratio}, e {level} {context}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"advanced_colors": {
|
||||||
|
"badge": "Sfondo medaglie",
|
||||||
|
"post": "Messaggi / Biografie",
|
||||||
|
"alert_neutral": "Neutro",
|
||||||
|
"alert_warning": "Attenzione",
|
||||||
|
"alert_error": "Errore",
|
||||||
|
"alert": "Sfondo degli avvertimenti",
|
||||||
|
"_tab_label": "Avanzate",
|
||||||
|
"tabs": "Etichette",
|
||||||
|
"disabled": "Disabilitato",
|
||||||
|
"selectedMenu": "Voce menù selezionata",
|
||||||
|
"selectedPost": "Messaggio selezionato",
|
||||||
|
"pressed": "Premuto",
|
||||||
|
"highlight": "Elementi evidenziati",
|
||||||
|
"icons": "Icone",
|
||||||
|
"poll": "Grafico sondaggi",
|
||||||
|
"underlay": "Sottostante",
|
||||||
|
"faint_text": "Testo sbiadito",
|
||||||
|
"inputs": "Campi d'immissione",
|
||||||
|
"buttons": "Pulsanti",
|
||||||
|
"borders": "Bordi",
|
||||||
|
"top_bar": "Barra superiore",
|
||||||
|
"panel_header": "Titolo pannello",
|
||||||
|
"badge_notification": "Notifica",
|
||||||
|
"popover": "Suggerimenti, menù, sbalzi"
|
||||||
|
},
|
||||||
|
"common_colors": {
|
||||||
|
"rgbo": "Icone, accenti, medaglie",
|
||||||
|
"foreground_hint": "Seleziona l'etichetta \"Avanzate\" per controlli più fini",
|
||||||
|
"main": "Colori comuni",
|
||||||
|
"_tab_label": "Comuni"
|
||||||
|
},
|
||||||
|
"shadows": {
|
||||||
|
"inset": "Includi",
|
||||||
|
"spread": "Spandi",
|
||||||
|
"blur": "Sfoca",
|
||||||
|
"shadow_id": "Ombra numero {value}",
|
||||||
|
"override": "Sostituisci",
|
||||||
|
"component": "Componente",
|
||||||
|
"_tab_label": "Luci ed ombre"
|
||||||
|
},
|
||||||
|
"radii": {
|
||||||
|
"_tab_label": "Raggio"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"enable_web_push_notifications": "Abilita notifiche web push",
|
"enable_web_push_notifications": "Abilita notifiche web push",
|
||||||
|
@ -229,7 +290,7 @@
|
||||||
"notifications": "Notifiche",
|
"notifications": "Notifiche",
|
||||||
"greentext": "Frecce da meme",
|
"greentext": "Frecce da meme",
|
||||||
"upload_a_photo": "Carica un'immagine",
|
"upload_a_photo": "Carica un'immagine",
|
||||||
"type_domains_to_mute": "Inserisci domini da zittire",
|
"type_domains_to_mute": "Cerca domini da zittire",
|
||||||
"theme_help_v2_2": "Le icone dietro alcuni elementi sono indicatori del contrasto fra testo e sfondo, passaci sopra col puntatore per ulteriori informazioni. Se si usano delle trasparenze, questi indicatori mostrano il peggior caso possibile.",
|
"theme_help_v2_2": "Le icone dietro alcuni elementi sono indicatori del contrasto fra testo e sfondo, passaci sopra col puntatore per ulteriori informazioni. Se si usano delle trasparenze, questi indicatori mostrano il peggior caso possibile.",
|
||||||
"theme_help_v2_1": "Puoi anche forzare colore ed opacità di alcuni elementi selezionando la casella. Usa il pulsante \"Azzera\" per azzerare tutte le forzature.",
|
"theme_help_v2_1": "Puoi anche forzare colore ed opacità di alcuni elementi selezionando la casella. Usa il pulsante \"Azzera\" per azzerare tutte le forzature.",
|
||||||
"useStreamingApiWarning": "(Sconsigliato, sperimentale, può saltare messaggi)",
|
"useStreamingApiWarning": "(Sconsigliato, sperimentale, può saltare messaggi)",
|
||||||
|
@ -273,7 +334,8 @@
|
||||||
"accent": "Accento",
|
"accent": "Accento",
|
||||||
"emoji_reactions_on_timeline": "Mostra emoji di reazione sulle sequenze",
|
"emoji_reactions_on_timeline": "Mostra emoji di reazione sulle sequenze",
|
||||||
"pad_emoji": "Affianca spazi agli emoji inseriti tramite selettore",
|
"pad_emoji": "Affianca spazi agli emoji inseriti tramite selettore",
|
||||||
"notification_blocks": "Bloccando un utente non riceverai più le sue notifiche né lo seguirai più."
|
"notification_blocks": "Bloccando un utente non riceverai più le sue notifiche né lo seguirai più.",
|
||||||
|
"mutes_and_blocks": "Zittiti e bloccati"
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"error_fetching": "Errore nell'aggiornamento",
|
"error_fetching": "Errore nell'aggiornamento",
|
||||||
|
|
|
@ -130,6 +130,7 @@
|
||||||
"background": "Фон",
|
"background": "Фон",
|
||||||
"bio": "Описание",
|
"bio": "Описание",
|
||||||
"btnRadius": "Кнопки",
|
"btnRadius": "Кнопки",
|
||||||
|
"bot": "Это аккаунт бота",
|
||||||
"cBlue": "Ответить, читать",
|
"cBlue": "Ответить, читать",
|
||||||
"cGreen": "Повторить",
|
"cGreen": "Повторить",
|
||||||
"cOrange": "Нравится",
|
"cOrange": "Нравится",
|
||||||
|
@ -456,9 +457,9 @@
|
||||||
},
|
},
|
||||||
"domain_mute_card": {
|
"domain_mute_card": {
|
||||||
"mute": "Игнорировать",
|
"mute": "Игнорировать",
|
||||||
"mute_progress": "В процессе...",
|
"mute_progress": "В процессе…",
|
||||||
"unmute": "Прекратить игнорирование",
|
"unmute": "Прекратить игнорирование",
|
||||||
"unmute_progress": "В процессе..."
|
"unmute_progress": "В процессе…"
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"export": "Экспорт",
|
"export": "Экспорт",
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* eslint-disable import/no-webpack-loader-syntax */
|
||||||
|
// This module exports only the notification part of the i18n,
|
||||||
|
// which is useful for the service worker
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
ar: require('../lib/notification-i18n-loader.js!./ar.json'),
|
||||||
|
ca: require('../lib/notification-i18n-loader.js!./ca.json'),
|
||||||
|
cs: require('../lib/notification-i18n-loader.js!./cs.json'),
|
||||||
|
de: require('../lib/notification-i18n-loader.js!./de.json'),
|
||||||
|
eo: require('../lib/notification-i18n-loader.js!./eo.json'),
|
||||||
|
es: require('../lib/notification-i18n-loader.js!./es.json'),
|
||||||
|
et: require('../lib/notification-i18n-loader.js!./et.json'),
|
||||||
|
eu: require('../lib/notification-i18n-loader.js!./eu.json'),
|
||||||
|
fi: require('../lib/notification-i18n-loader.js!./fi.json'),
|
||||||
|
fr: require('../lib/notification-i18n-loader.js!./fr.json'),
|
||||||
|
ga: require('../lib/notification-i18n-loader.js!./ga.json'),
|
||||||
|
he: require('../lib/notification-i18n-loader.js!./he.json'),
|
||||||
|
hu: require('../lib/notification-i18n-loader.js!./hu.json'),
|
||||||
|
it: require('../lib/notification-i18n-loader.js!./it.json'),
|
||||||
|
ja: require('../lib/notification-i18n-loader.js!./ja_pedantic.json'),
|
||||||
|
ja_easy: require('../lib/notification-i18n-loader.js!./ja_easy.json'),
|
||||||
|
ko: require('../lib/notification-i18n-loader.js!./ko.json'),
|
||||||
|
nb: require('../lib/notification-i18n-loader.js!./nb.json'),
|
||||||
|
nl: require('../lib/notification-i18n-loader.js!./nl.json'),
|
||||||
|
oc: require('../lib/notification-i18n-loader.js!./oc.json'),
|
||||||
|
pl: require('../lib/notification-i18n-loader.js!./pl.json'),
|
||||||
|
pt: require('../lib/notification-i18n-loader.js!./pt.json'),
|
||||||
|
ro: require('../lib/notification-i18n-loader.js!./ro.json'),
|
||||||
|
ru: require('../lib/notification-i18n-loader.js!./ru.json'),
|
||||||
|
te: require('../lib/notification-i18n-loader.js!./te.json'),
|
||||||
|
zh: require('../lib/notification-i18n-loader.js!./zh.json'),
|
||||||
|
en: require('../lib/notification-i18n-loader.js!./en.json')
|
||||||
|
}
|
||||||
|
|
||||||
|
export default messages
|
|
@ -0,0 +1,12 @@
|
||||||
|
// This somewhat mysterious module will load a json string
|
||||||
|
// and then extract only the 'notifications' part. This is
|
||||||
|
// meant to be used to load the partial i18n we need for
|
||||||
|
// the service worker.
|
||||||
|
module.exports = function (source) {
|
||||||
|
var object = JSON.parse(source)
|
||||||
|
var smol = {
|
||||||
|
notifications: object.notifications || {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.stringify(smol)
|
||||||
|
}
|
|
@ -1,13 +1,12 @@
|
||||||
import merge from 'lodash.merge'
|
import merge from 'lodash.merge'
|
||||||
import objectPath from 'object-path'
|
|
||||||
import localforage from 'localforage'
|
import localforage from 'localforage'
|
||||||
import { each } from 'lodash'
|
import { each, get, set } from 'lodash'
|
||||||
|
|
||||||
let loaded = false
|
let loaded = false
|
||||||
|
|
||||||
const defaultReducer = (state, paths) => (
|
const defaultReducer = (state, paths) => (
|
||||||
paths.length === 0 ? state : paths.reduce((substate, path) => {
|
paths.length === 0 ? state : paths.reduce((substate, path) => {
|
||||||
objectPath.set(substate, path, objectPath.get(state, path))
|
set(substate, path, get(state, path))
|
||||||
return substate
|
return substate
|
||||||
}, {})
|
}, {})
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import { getPreset, applyTheme } from '../services/style_setter/style_setter.js'
|
import { getPreset, applyTheme } from '../services/style_setter/style_setter.js'
|
||||||
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
||||||
|
import apiService from '../services/api/api.service.js'
|
||||||
import { instanceDefaultProperties } from './config.js'
|
import { instanceDefaultProperties } from './config.js'
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
@ -48,6 +49,7 @@ const defaultState = {
|
||||||
postFormats: [],
|
postFormats: [],
|
||||||
restrictedNicknames: [],
|
restrictedNicknames: [],
|
||||||
safeDM: true,
|
safeDM: true,
|
||||||
|
knownDomains: [],
|
||||||
|
|
||||||
// Feature-set, apparently, not everything here is reported...
|
// Feature-set, apparently, not everything here is reported...
|
||||||
chatAvailable: false,
|
chatAvailable: false,
|
||||||
|
@ -80,6 +82,9 @@ const instance = {
|
||||||
if (typeof value !== 'undefined') {
|
if (typeof value !== 'undefined') {
|
||||||
set(state, name, value)
|
set(state, name, value)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setKnownDomains (state, domains) {
|
||||||
|
state.knownDomains = domains
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
@ -182,6 +187,18 @@ const instance = {
|
||||||
state.emojiFetched = true
|
state.emojiFetched = true
|
||||||
dispatch('getStaticEmoji')
|
dispatch('getStaticEmoji')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getKnownDomains ({ commit, rootState }) {
|
||||||
|
try {
|
||||||
|
const result = await apiService.fetchKnownDomains({
|
||||||
|
credentials: rootState.users.currentUser.credentials
|
||||||
|
})
|
||||||
|
commit('setKnownDomains', result)
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Can't load known domains")
|
||||||
|
console.warn(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
omitBy
|
omitBy
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import { isStatusNotification } from '../services/notification_utils/notification_utils.js'
|
import { isStatusNotification, prepareNotificationObject } from '../services/notification_utils/notification_utils.js'
|
||||||
import apiService from '../services/api/api.service.js'
|
import apiService from '../services/api/api.service.js'
|
||||||
import { muteWordHits } from '../services/status_parser/status_parser.js'
|
import { muteWordHits } from '../services/status_parser/status_parser.js'
|
||||||
|
|
||||||
|
@ -344,42 +344,7 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot
|
||||||
state.notifications.idStore[notification.id] = notification
|
state.notifications.idStore[notification.id] = notification
|
||||||
|
|
||||||
if ('Notification' in window && window.Notification.permission === 'granted') {
|
if ('Notification' in window && window.Notification.permission === 'granted') {
|
||||||
const notifObj = {}
|
const notifObj = prepareNotificationObject(notification, rootGetters.i18n)
|
||||||
const status = notification.status
|
|
||||||
const title = notification.from_profile.name
|
|
||||||
notifObj.icon = notification.from_profile.profile_image_url
|
|
||||||
let i18nString
|
|
||||||
switch (notification.type) {
|
|
||||||
case 'like':
|
|
||||||
i18nString = 'favorited_you'
|
|
||||||
break
|
|
||||||
case 'repeat':
|
|
||||||
i18nString = 'repeated_you'
|
|
||||||
break
|
|
||||||
case 'follow':
|
|
||||||
i18nString = 'followed_you'
|
|
||||||
break
|
|
||||||
case 'move':
|
|
||||||
i18nString = 'migrated_to'
|
|
||||||
break
|
|
||||||
case 'follow_request':
|
|
||||||
i18nString = 'follow_request'
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notification.type === 'pleroma:emoji_reaction') {
|
|
||||||
notifObj.body = rootGetters.i18n.t('notifications.reacted_with', [notification.emoji])
|
|
||||||
} else if (i18nString) {
|
|
||||||
notifObj.body = rootGetters.i18n.t('notifications.' + i18nString)
|
|
||||||
} else if (isStatusNotification(notification.type)) {
|
|
||||||
notifObj.body = notification.status.text
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shows first attached non-nsfw image, if any. Should add configuration for this somehow...
|
|
||||||
if (status && status.attachments && status.attachments.length > 0 && !status.nsfw &&
|
|
||||||
status.attachments[0].mimetype.startsWith('image/')) {
|
|
||||||
notifObj.image = status.attachments[0].url
|
|
||||||
}
|
|
||||||
|
|
||||||
const reasonsToMuteNotif = (
|
const reasonsToMuteNotif = (
|
||||||
notification.seen ||
|
notification.seen ||
|
||||||
|
@ -393,7 +358,7 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (!reasonsToMuteNotif) {
|
if (!reasonsToMuteNotif) {
|
||||||
let desktopNotification = new window.Notification(title, notifObj)
|
let desktopNotification = new window.Notification(notifObj.title, notifObj)
|
||||||
// Chrome is known for not closing notifications automatically
|
// Chrome is known for not closing notifications automatically
|
||||||
// according to MDN, anyway.
|
// according to MDN, anyway.
|
||||||
setTimeout(desktopNotification.close.bind(desktopNotification), 5000)
|
setTimeout(desktopNotification.close.bind(desktopNotification), 5000)
|
||||||
|
|
|
@ -435,10 +435,10 @@ const users = {
|
||||||
store.commit('setUserForNotification', notification)
|
store.commit('setUserForNotification', notification)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
searchUsers (store, { query }) {
|
searchUsers ({ rootState, commit }, { query }) {
|
||||||
return store.rootState.api.backendInteractor.searchUsers({ query })
|
return rootState.api.backendInteractor.searchUsers({ query })
|
||||||
.then((users) => {
|
.then((users) => {
|
||||||
store.commit('addNewUsers', users)
|
commit('addNewUsers', users)
|
||||||
return users
|
return users
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { each, map, concat, last, get } from 'lodash'
|
import { each, map, concat, last, get } from 'lodash'
|
||||||
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
||||||
import 'whatwg-fetch'
|
|
||||||
import { RegistrationError, StatusCodeError } from '../errors/errors'
|
import { RegistrationError, StatusCodeError } from '../errors/errors'
|
||||||
|
|
||||||
/* eslint-env browser */
|
/* eslint-env browser */
|
||||||
|
@ -75,6 +74,7 @@ const MASTODON_SEARCH_2 = `/api/v2/search`
|
||||||
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
||||||
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
||||||
const MASTODON_STREAMING = '/api/v1/streaming'
|
const MASTODON_STREAMING = '/api/v1/streaming'
|
||||||
|
const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
|
||||||
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions`
|
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions`
|
||||||
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
|
@ -995,6 +995,10 @@ const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchKnownDomains = ({ credentials }) => {
|
||||||
|
return promisedRequest({ url: MASTODON_KNOWN_DOMAIN_LIST_URL, credentials })
|
||||||
|
}
|
||||||
|
|
||||||
const fetchDomainMutes = ({ credentials }) => {
|
const fetchDomainMutes = ({ credentials }) => {
|
||||||
return promisedRequest({ url: MASTODON_DOMAIN_BLOCKS_URL, credentials })
|
return promisedRequest({ url: MASTODON_DOMAIN_BLOCKS_URL, credentials })
|
||||||
}
|
}
|
||||||
|
@ -1193,6 +1197,7 @@ const apiService = {
|
||||||
updateNotificationSettings,
|
updateNotificationSettings,
|
||||||
search2,
|
search2,
|
||||||
searchUsers,
|
searchUsers,
|
||||||
|
fetchKnownDomains,
|
||||||
fetchDomainMutes,
|
fetchDomainMutes,
|
||||||
muteDomain,
|
muteDomain,
|
||||||
unmuteDomain
|
unmuteDomain
|
||||||
|
|
|
@ -56,6 +56,12 @@ export const parseUser = (data) => {
|
||||||
value: addEmojis(field.value, data.emojis)
|
value: addEmojis(field.value, data.emojis)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
output.fields_text = data.fields.map(field => {
|
||||||
|
return {
|
||||||
|
name: unescape(field.name.replace(/<[^>]*>/g, '')),
|
||||||
|
value: unescape(field.value.replace(/<[^>]*>/g, ''))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Utilize avatar_static for gif avatars?
|
// Utilize avatar_static for gif avatars?
|
||||||
output.profile_image_url = data.avatar
|
output.profile_image_url = data.avatar
|
||||||
|
@ -258,6 +264,12 @@ export const parseStatus = (data) => {
|
||||||
output.summary_html = addEmojis(escape(data.spoiler_text), data.emojis)
|
output.summary_html = addEmojis(escape(data.spoiler_text), data.emojis)
|
||||||
output.external_url = data.url
|
output.external_url = data.url
|
||||||
output.poll = data.poll
|
output.poll = data.poll
|
||||||
|
if (output.poll) {
|
||||||
|
output.poll.options = (output.poll.options || []).map(field => ({
|
||||||
|
...field,
|
||||||
|
title_html: addEmojis(field.title, data.emojis)
|
||||||
|
}))
|
||||||
|
}
|
||||||
output.pinned = data.pinned
|
output.pinned = data.pinned
|
||||||
output.muted = data.muted
|
output.muted = data.muted
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -43,3 +43,47 @@ export const filteredNotificationsFromStore = (store, types) => {
|
||||||
|
|
||||||
export const unseenNotificationsFromStore = store =>
|
export const unseenNotificationsFromStore = store =>
|
||||||
filter(filteredNotificationsFromStore(store), ({ seen }) => !seen)
|
filter(filteredNotificationsFromStore(store), ({ seen }) => !seen)
|
||||||
|
|
||||||
|
export const prepareNotificationObject = (notification, i18n) => {
|
||||||
|
const notifObj = {
|
||||||
|
tag: notification.id
|
||||||
|
}
|
||||||
|
const status = notification.status
|
||||||
|
const title = notification.from_profile.name
|
||||||
|
notifObj.title = title
|
||||||
|
notifObj.icon = notification.from_profile.profile_image_url
|
||||||
|
let i18nString
|
||||||
|
switch (notification.type) {
|
||||||
|
case 'like':
|
||||||
|
i18nString = 'favorited_you'
|
||||||
|
break
|
||||||
|
case 'repeat':
|
||||||
|
i18nString = 'repeated_you'
|
||||||
|
break
|
||||||
|
case 'follow':
|
||||||
|
i18nString = 'followed_you'
|
||||||
|
break
|
||||||
|
case 'move':
|
||||||
|
i18nString = 'migrated_to'
|
||||||
|
break
|
||||||
|
case 'follow_request':
|
||||||
|
i18nString = 'follow_request'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notification.type === 'pleroma:emoji_reaction') {
|
||||||
|
notifObj.body = i18n.t('notifications.reacted_with', [notification.emoji])
|
||||||
|
} else if (i18nString) {
|
||||||
|
notifObj.body = i18n.t('notifications.' + i18nString)
|
||||||
|
} else if (isStatusNotification(notification.type)) {
|
||||||
|
notifObj.body = notification.status.text
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows first attached non-nsfw image, if any. Should add configuration for this somehow...
|
||||||
|
if (status && status.attachments && status.attachments.length > 0 && !status.nsfw &&
|
||||||
|
status.attachments[0].mimetype.startsWith('image/')) {
|
||||||
|
notifObj.image = status.attachments[0].url
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifObj
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,4 @@
|
||||||
import { filter } from 'lodash'
|
import { filter } from 'lodash'
|
||||||
import sanitize from 'sanitize-html'
|
|
||||||
|
|
||||||
export const removeAttachmentLinks = (html) => {
|
|
||||||
return sanitize(html, {
|
|
||||||
allowedTags: false,
|
|
||||||
allowedAttributes: false,
|
|
||||||
exclusiveFilter: ({ tag, attribs }) => tag === 'a' && typeof attribs.class === 'string' && attribs.class.match(/attachment/)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const parse = (html) => {
|
|
||||||
return removeAttachmentLinks(html)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const muteWordHits = (status, muteWords) => {
|
export const muteWordHits = (status, muteWords) => {
|
||||||
const statusText = status.text.toLowerCase()
|
const statusText = status.text.toLowerCase()
|
||||||
|
@ -22,5 +9,3 @@ export const muteWordHits = (status, muteWords) => {
|
||||||
|
|
||||||
return hits
|
return hits
|
||||||
}
|
}
|
||||||
|
|
||||||
export default parse
|
|
||||||
|
|
|
@ -356,6 +356,12 @@ export const SLOT_INHERITANCE = {
|
||||||
textColor: 'preserve'
|
textColor: 'preserve'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
postGreentext: {
|
||||||
|
depends: ['cGreen'],
|
||||||
|
layer: 'bg',
|
||||||
|
textColor: 'preserve'
|
||||||
|
},
|
||||||
|
|
||||||
border: {
|
border: {
|
||||||
depends: ['fg'],
|
depends: ['fg'],
|
||||||
opacity: 'border',
|
opacity: 'border',
|
||||||
|
|
47
src/sw.js
47
src/sw.js
|
@ -1,6 +1,19 @@
|
||||||
/* eslint-env serviceworker */
|
/* eslint-env serviceworker */
|
||||||
|
|
||||||
import localForage from 'localforage'
|
import localForage from 'localforage'
|
||||||
|
import { parseNotification } from './services/entity_normalizer/entity_normalizer.service.js'
|
||||||
|
import { prepareNotificationObject } from './services/notification_utils/notification_utils.js'
|
||||||
|
import Vue from 'vue'
|
||||||
|
import VueI18n from 'vue-i18n'
|
||||||
|
import messages from './i18n/service_worker_messages.js'
|
||||||
|
|
||||||
|
Vue.use(VueI18n)
|
||||||
|
const i18n = new VueI18n({
|
||||||
|
// By default, use the browser locale, we will update it if neccessary
|
||||||
|
locale: 'en',
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
messages
|
||||||
|
})
|
||||||
|
|
||||||
function isEnabled () {
|
function isEnabled () {
|
||||||
return localForage.getItem('vuex-lz')
|
return localForage.getItem('vuex-lz')
|
||||||
|
@ -12,15 +25,33 @@ function getWindowClients () {
|
||||||
.then((clientList) => clientList.filter(({ type }) => type === 'window'))
|
.then((clientList) => clientList.filter(({ type }) => type === 'window'))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addEventListener('push', (event) => {
|
const setLocale = async () => {
|
||||||
if (event.data) {
|
const state = await localForage.getItem('vuex-lz')
|
||||||
event.waitUntil(isEnabled().then((isEnabled) => {
|
const locale = state.config.interfaceLanguage || 'en'
|
||||||
return isEnabled && getWindowClients().then((list) => {
|
i18n.locale = locale
|
||||||
const data = event.data.json()
|
}
|
||||||
|
|
||||||
if (list.length === 0) return self.registration.showNotification(data.title, data)
|
const maybeShowNotification = async (event) => {
|
||||||
})
|
const enabled = await isEnabled()
|
||||||
}))
|
const activeClients = await getWindowClients()
|
||||||
|
await setLocale()
|
||||||
|
if (enabled && (activeClients.length === 0)) {
|
||||||
|
const data = event.data.json()
|
||||||
|
|
||||||
|
const url = `${self.registration.scope}api/v1/notifications/${data.notification_id}`
|
||||||
|
const notification = await fetch(url, { headers: { Authorization: 'Bearer ' + data.access_token } })
|
||||||
|
const notificationJson = await notification.json()
|
||||||
|
const parsedNotification = parseNotification(notificationJson)
|
||||||
|
|
||||||
|
const res = prepareNotificationObject(parsedNotification, i18n)
|
||||||
|
|
||||||
|
self.registration.showNotification(res.title, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addEventListener('push', async (event) => {
|
||||||
|
if (event.data) {
|
||||||
|
event.waitUntil(maybeShowNotification(event))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
<h4>Terms of Service</h4>
|
<h4>Terms of Service</h4>
|
||||||
|
|
||||||
<p>This is a placeholder ToS. Edit <code>"/static/terms-of-service.html"</code> to make it fit the needs of your instance.</p>
|
<p>This is the default placeholder ToS. You should copy it over to your static folder and edit it to fit the needs of your instance.</p>
|
||||||
|
|
||||||
|
<p>To do so, place a file at <code>"/instance/static/terms-of-service.html"</code> in your
|
||||||
|
Pleroma install containing the real ToS for your instance.</p>
|
||||||
|
<p>See the <a href='https://docs.pleroma.social/backend/configuration/static_dir/'>Pleroma documentation</a> for more information.</p>
|
||||||
|
<br>
|
||||||
<img src="/static/logo.png" style="display: block; margin: auto; max-width: 100%; height: 50px; object-fit: contain;" />
|
<img src="/static/logo.png" style="display: block; margin: auto; max-width: 100%; height: 50px; object-fit: contain;" />
|
||||||
|
|
|
@ -286,7 +286,9 @@
|
||||||
"cGreen": "#008000",
|
"cGreen": "#008000",
|
||||||
"cOrange": "#808000",
|
"cOrange": "#808000",
|
||||||
"highlight": "--accent",
|
"highlight": "--accent",
|
||||||
"selectedPost": "--bg,-10"
|
"selectedPost": "--bg,-10",
|
||||||
|
"selectedMenu": "--accent",
|
||||||
|
"selectedMenuPopover": "--accent"
|
||||||
},
|
},
|
||||||
"radii": {
|
"radii": {
|
||||||
"btn": "0",
|
"btn": "0",
|
||||||
|
|
|
@ -277,7 +277,9 @@
|
||||||
"cGreen": "#008000",
|
"cGreen": "#008000",
|
||||||
"cOrange": "#808000",
|
"cOrange": "#808000",
|
||||||
"highlight": "--accent",
|
"highlight": "--accent",
|
||||||
"selectedPost": "--bg,-10"
|
"selectedPost": "--bg,-10",
|
||||||
|
"selectedMenu": "--accent",
|
||||||
|
"selectedMenuPopover": "--accent"
|
||||||
},
|
},
|
||||||
"radii": {
|
"radii": {
|
||||||
"btn": "0",
|
"btn": "0",
|
||||||
|
|
|
@ -259,7 +259,9 @@
|
||||||
"cGreen": "#669966",
|
"cGreen": "#669966",
|
||||||
"cOrange": "#cc6633",
|
"cOrange": "#cc6633",
|
||||||
"highlight": "--accent",
|
"highlight": "--accent",
|
||||||
"selectedPost": "--bg,-10"
|
"selectedPost": "--bg,-10",
|
||||||
|
"selectedMenu": "--accent",
|
||||||
|
"selectedMenuPopover": "--accent"
|
||||||
},
|
},
|
||||||
"radii": {
|
"radii": {
|
||||||
"btn": "0",
|
"btn": "0",
|
||||||
|
|
|
@ -290,6 +290,19 @@ describe('API Entities normalizer', () => {
|
||||||
expect(field).to.have.property('value').that.contains('<img')
|
expect(field).to.have.property('value').that.contains('<img')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('removes html tags from user profile fields', () => {
|
||||||
|
const user = makeMockUserMasto({ emojis: makeMockEmojiMasto(), fields: [{ name: 'user', value: '<a rel="me" href="https://example.com/@user">@user</a>' }] })
|
||||||
|
|
||||||
|
const parsedUser = parseUser(user)
|
||||||
|
|
||||||
|
expect(parsedUser).to.have.property('fields_text').to.be.an('array')
|
||||||
|
|
||||||
|
const field = parsedUser.fields_text[0]
|
||||||
|
|
||||||
|
expect(field).to.have.property('name').that.equal('user')
|
||||||
|
expect(field).to.have.property('value').that.equal('@user')
|
||||||
|
})
|
||||||
|
|
||||||
it('adds hide_follows and hide_followers user settings', () => {
|
it('adds hide_follows and hide_followers user settings', () => {
|
||||||
const user = makeMockUserMasto({ pleroma: { hide_followers: true, hide_follows: false, hide_followers_count: false, hide_follows_count: true } })
|
const user = makeMockUserMasto({ pleroma: { hide_followers: true, hide_follows: false, hide_followers_count: false, hide_follows_count: true } })
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import { removeAttachmentLinks } from '../../../../../src/services/status_parser/status_parser.js'
|
|
||||||
|
|
||||||
const example = '<div class="status-content">@<a href="https://sealion.club/user/4" class="h-card mention" title="dewoo">dwmatiz</a> <a href="https://social.heldscal.la/file/3deb764ada10ce64a61b7a070b75dac45f86d2d5bf213bf18873da71d8714d86.png" title="https://social.heldscal.la/file/3deb764ada10ce64a61b7a070b75dac45f86d2d5bf213bf18873da71d8714d86.png" class="attachment" id="attachment-159853" rel="nofollow external">https://social.heldscal.la/attachment/159853</a></div>'
|
|
||||||
|
|
||||||
describe('statusParser.removeAttachmentLinks', () => {
|
|
||||||
const exampleWithoutAttachmentLinks = '<div class="status-content">@<a href="https://sealion.club/user/4" class="h-card mention" title="dewoo">dwmatiz</a> </div>'
|
|
||||||
|
|
||||||
it('removes attachment links', () => {
|
|
||||||
const parsed = removeAttachmentLinks(example)
|
|
||||||
expect(parsed).to.eql(exampleWithoutAttachmentLinks)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('works when the class is empty', () => {
|
|
||||||
const parsed = removeAttachmentLinks('<a></a>')
|
|
||||||
expect(parsed).to.eql('<a></a>')
|
|
||||||
})
|
|
||||||
})
|
|
100
yarn.lock
100
yarn.lock
|
@ -1062,7 +1062,7 @@ array-union@^1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
array-uniq "^1.0.1"
|
array-uniq "^1.0.1"
|
||||||
|
|
||||||
array-uniq@^1.0.1, array-uniq@^1.0.2:
|
array-uniq@^1.0.1:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
|
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
|
||||||
|
|
||||||
|
@ -2545,7 +2545,7 @@ domain-browser@^1.1.1:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
|
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
|
||||||
|
|
||||||
domelementtype@1, domelementtype@^1.3.0:
|
domelementtype@1:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
||||||
|
|
||||||
|
@ -2559,12 +2559,6 @@ domhandler@2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
domelementtype "1"
|
domelementtype "1"
|
||||||
|
|
||||||
domhandler@^2.3.0:
|
|
||||||
version "2.4.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
|
|
||||||
dependencies:
|
|
||||||
domelementtype "1"
|
|
||||||
|
|
||||||
domutils@1.1:
|
domutils@1.1:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485"
|
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485"
|
||||||
|
@ -2578,13 +2572,6 @@ domutils@1.5.1:
|
||||||
dom-serializer "0"
|
dom-serializer "0"
|
||||||
domelementtype "1"
|
domelementtype "1"
|
||||||
|
|
||||||
domutils@^1.5.1:
|
|
||||||
version "1.7.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
|
|
||||||
dependencies:
|
|
||||||
dom-serializer "0"
|
|
||||||
domelementtype "1"
|
|
||||||
|
|
||||||
duplexer2@~0.1.4:
|
duplexer2@~0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
|
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
|
||||||
|
@ -2711,7 +2698,7 @@ ent@~2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
|
resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
|
||||||
|
|
||||||
entities@^1.1.1, entities@~1.1.1:
|
entities@~1.1.1:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
||||||
|
|
||||||
|
@ -3762,17 +3749,6 @@ html-webpack-plugin@^3.0.0, html-webpack-plugin@^3.2.0:
|
||||||
toposort "^1.0.0"
|
toposort "^1.0.0"
|
||||||
util.promisify "1.0.0"
|
util.promisify "1.0.0"
|
||||||
|
|
||||||
htmlparser2@^3.10.0:
|
|
||||||
version "3.10.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464"
|
|
||||||
dependencies:
|
|
||||||
domelementtype "^1.3.0"
|
|
||||||
domhandler "^2.3.0"
|
|
||||||
domutils "^1.5.1"
|
|
||||||
entities "^1.1.1"
|
|
||||||
inherits "^2.0.1"
|
|
||||||
readable-stream "^3.0.6"
|
|
||||||
|
|
||||||
htmlparser2@~3.3.0:
|
htmlparser2@~3.3.0:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe"
|
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe"
|
||||||
|
@ -4757,10 +4733,6 @@ lodash.clone@3.0.3:
|
||||||
lodash._bindcallback "^3.0.0"
|
lodash._bindcallback "^3.0.0"
|
||||||
lodash._isiterateecall "^3.0.0"
|
lodash._isiterateecall "^3.0.0"
|
||||||
|
|
||||||
lodash.clonedeep@^4.5.0:
|
|
||||||
version "4.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
|
||||||
|
|
||||||
lodash.create@3.1.1:
|
lodash.create@3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
|
resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
|
||||||
|
@ -4780,10 +4752,6 @@ lodash.defaultsdeep@4.3.2:
|
||||||
lodash.mergewith "^4.0.0"
|
lodash.mergewith "^4.0.0"
|
||||||
lodash.rest "^4.0.0"
|
lodash.rest "^4.0.0"
|
||||||
|
|
||||||
lodash.escaperegexp@^4.1.2:
|
|
||||||
version "4.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
|
|
||||||
|
|
||||||
lodash.find@^3.2.1:
|
lodash.find@^3.2.1:
|
||||||
version "3.2.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-3.2.1.tgz#046e319f3ace912ac6c9246c7f683c5ec07b36ad"
|
resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-3.2.1.tgz#046e319f3ace912ac6c9246c7f683c5ec07b36ad"
|
||||||
|
@ -4815,14 +4783,10 @@ lodash.isplainobject@^3.0.0, lodash.isplainobject@^3.2.0:
|
||||||
lodash.isarguments "^3.0.0"
|
lodash.isarguments "^3.0.0"
|
||||||
lodash.keysin "^3.0.0"
|
lodash.keysin "^3.0.0"
|
||||||
|
|
||||||
lodash.isplainobject@^4.0.0, lodash.isplainobject@^4.0.6:
|
lodash.isplainobject@^4.0.0:
|
||||||
version "4.0.6"
|
version "4.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||||
|
|
||||||
lodash.isstring@^4.0.1:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
|
||||||
|
|
||||||
lodash.istypedarray@^3.0.0:
|
lodash.istypedarray@^3.0.0:
|
||||||
version "3.0.6"
|
version "3.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz#c9a477498607501d8e8494d283b87c39281cef62"
|
resolved "https://registry.yarnpkg.com/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz#c9a477498607501d8e8494d283b87c39281cef62"
|
||||||
|
@ -4871,7 +4835,7 @@ lodash.merge@^3.3.2:
|
||||||
lodash.keysin "^3.0.0"
|
lodash.keysin "^3.0.0"
|
||||||
lodash.toplainobject "^3.0.0"
|
lodash.toplainobject "^3.0.0"
|
||||||
|
|
||||||
lodash.mergewith@^4.0.0, lodash.mergewith@^4.6.1:
|
lodash.mergewith@^4.0.0:
|
||||||
version "4.6.1"
|
version "4.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
|
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
|
||||||
|
|
||||||
|
@ -5538,10 +5502,6 @@ object-keys@^1.0.11, object-keys@^1.0.12:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||||
|
|
||||||
object-path@^0.11.3:
|
|
||||||
version "0.11.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949"
|
|
||||||
|
|
||||||
object-visit@^1.0.0:
|
object-visit@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
|
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
|
||||||
|
@ -6245,14 +6205,6 @@ postcss@^7.0.0:
|
||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
supports-color "^6.1.0"
|
supports-color "^6.1.0"
|
||||||
|
|
||||||
postcss@^7.0.5:
|
|
||||||
version "7.0.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.8.tgz#2a3c5f2bdd00240cd0d0901fd998347c93d36696"
|
|
||||||
dependencies:
|
|
||||||
chalk "^2.4.2"
|
|
||||||
source-map "^0.6.1"
|
|
||||||
supports-color "^6.0.0"
|
|
||||||
|
|
||||||
prelude-ls@~1.1.2:
|
prelude-ls@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||||
|
@ -6521,14 +6473,6 @@ readable-stream@1.1.x:
|
||||||
isarray "0.0.1"
|
isarray "0.0.1"
|
||||||
string_decoder "~0.10.x"
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
readable-stream@^3.0.6:
|
|
||||||
version "3.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06"
|
|
||||||
dependencies:
|
|
||||||
inherits "^2.0.3"
|
|
||||||
string_decoder "^1.1.1"
|
|
||||||
util-deprecate "^1.0.1"
|
|
||||||
|
|
||||||
readdirp@^2.2.1:
|
readdirp@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
|
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
|
||||||
|
@ -6839,21 +6783,6 @@ samsam@1.x, samsam@^1.1.3:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50"
|
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50"
|
||||||
|
|
||||||
sanitize-html@^1.13.0:
|
|
||||||
version "1.20.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.20.0.tgz#9a602beb1c9faf960fb31f9890f61911cc4d9156"
|
|
||||||
dependencies:
|
|
||||||
chalk "^2.4.1"
|
|
||||||
htmlparser2 "^3.10.0"
|
|
||||||
lodash.clonedeep "^4.5.0"
|
|
||||||
lodash.escaperegexp "^4.1.2"
|
|
||||||
lodash.isplainobject "^4.0.6"
|
|
||||||
lodash.isstring "^4.0.1"
|
|
||||||
lodash.mergewith "^4.6.1"
|
|
||||||
postcss "^7.0.5"
|
|
||||||
srcset "^1.0.0"
|
|
||||||
xtend "^4.0.1"
|
|
||||||
|
|
||||||
"sass-loader@git://github.com/webpack-contrib/sass-loader":
|
"sass-loader@git://github.com/webpack-contrib/sass-loader":
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
resolved "git://github.com/webpack-contrib/sass-loader#e279f2a129eee0bd0b624b5acd498f23a81ee35e"
|
resolved "git://github.com/webpack-contrib/sass-loader#e279f2a129eee0bd0b624b5acd498f23a81ee35e"
|
||||||
|
@ -7225,13 +7154,6 @@ sprintf-js@~1.0.2:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
|
|
||||||
srcset@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef"
|
|
||||||
dependencies:
|
|
||||||
array-uniq "^1.0.2"
|
|
||||||
number-is-nan "^1.0.0"
|
|
||||||
|
|
||||||
sshpk@^1.7.0:
|
sshpk@^1.7.0:
|
||||||
version "1.16.0"
|
version "1.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.0.tgz#1d4963a2fbffe58050aa9084ca20be81741c07de"
|
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.0.tgz#1d4963a2fbffe58050aa9084ca20be81741c07de"
|
||||||
|
@ -7331,7 +7253,7 @@ string-width@^3.0.0:
|
||||||
is-fullwidth-code-point "^2.0.0"
|
is-fullwidth-code-point "^2.0.0"
|
||||||
strip-ansi "^5.1.0"
|
strip-ansi "^5.1.0"
|
||||||
|
|
||||||
string_decoder@^1.0.0, string_decoder@^1.1.1:
|
string_decoder@^1.0.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
|
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7415,7 +7337,7 @@ supports-color@^5.3.0, supports-color@^5.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^3.0.0"
|
has-flag "^3.0.0"
|
||||||
|
|
||||||
supports-color@^6.0.0, supports-color@^6.1.0:
|
supports-color@^6.1.0:
|
||||||
version "6.1.0"
|
version "6.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7780,7 +7702,7 @@ useragent@2.3.0:
|
||||||
lru-cache "4.1.x"
|
lru-cache "4.1.x"
|
||||||
tmp "0.0.x"
|
tmp "0.0.x"
|
||||||
|
|
||||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
|
||||||
|
@ -8015,10 +7937,6 @@ webpack@^4.0.0:
|
||||||
watchpack "^1.5.0"
|
watchpack "^1.5.0"
|
||||||
webpack-sources "^1.3.0"
|
webpack-sources "^1.3.0"
|
||||||
|
|
||||||
whatwg-fetch@^2.0.3:
|
|
||||||
version "2.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
|
|
||||||
|
|
||||||
whet.extend@~0.9.9:
|
whet.extend@~0.9.9:
|
||||||
version "0.9.9"
|
version "0.9.9"
|
||||||
resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"
|
resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"
|
||||||
|
@ -8090,7 +8008,7 @@ xregexp@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
|
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
|
||||||
|
|
||||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
|
xtend@^4.0.0, xtend@~4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue