aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md14
-rw-r--r--package.json1
-rw-r--r--src/components/account_actions/account_actions.js4
-rw-r--r--src/components/account_actions/account_actions.vue21
-rw-r--r--src/components/emoji_reactions/emoji_reactions.js11
-rw-r--r--src/components/emoji_reactions/emoji_reactions.vue33
-rw-r--r--src/components/extra_buttons/extra_buttons.js3
-rw-r--r--src/components/extra_buttons/extra_buttons.vue14
-rw-r--r--src/components/moderation_tools/moderation_tools.js11
-rw-r--r--src/components/moderation_tools/moderation_tools.vue17
-rw-r--r--src/components/notification/notification.vue2
-rw-r--r--src/components/notifications/notifications.scss1
-rw-r--r--src/components/popover/popover.js156
-rw-r--r--src/components/popover/popover.vue118
-rw-r--r--src/components/popper/popper.scss164
-rw-r--r--src/components/react_button/react_button.js23
-rw-r--r--src/components/react_button/react_button.vue32
-rw-r--r--src/components/registration/registration.vue3
-rw-r--r--src/components/status/status.vue11
-rw-r--r--src/components/status_popover/status_popover.js11
-rw-r--r--src/components/status_popover/status_popover.vue74
-rw-r--r--src/i18n/en.json3
-rw-r--r--src/i18n/fi.json3
-rw-r--r--src/i18n/pl.json320
-rw-r--r--src/main.js8
-rw-r--r--src/modules/config.js1
-rw-r--r--src/modules/instance.js10
-rw-r--r--src/modules/statuses.js2
-rw-r--r--src/services/api/api.service.js18
-rw-r--r--src/services/theme_data/theme_data.service.js41
-rw-r--r--static/styles.json4
-rw-r--r--static/themes/pleroma-dark.json191
-rw-r--r--static/themes/pleroma-light.json219
-rw-r--r--yarn.lock19
34 files changed, 1208 insertions, 355 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1cdd604b..375e560f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,17 @@ 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/).
## [Unreleased]
+
+## [2.0.2] - 2020-04-08
+### Fixed
+- Favorite/Repeat avatars not showing up on private instances/non-public posts
+- Autocorrect getting triggered in the captcha field
+- Overflow on long domains in follow/move notifications
+
+### Changed
+- Polish translation updated
+
+## [2.0.0] - 2020-02-28
### Added
- Tons of color slots including ones for hover/pressed/toggled buttons
- Experimental `--variable[,mod]` syntax support for color slots in themes. the `mod` makes color brighter/darker depending on background color (makes darker color brighter/darker depending on background color)
@@ -16,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Emoji reactions for statuses
- MRF keyword policy disclosure
### Changed
+- Updated Pleroma default themes
- theme engine update to 3 (themes v2.1 introduction)
- massive internal changes in theme engine - slowly away from "generate things separately with spaghetti code" towards "feed all data into single 'generateTheme' function and declare slot inheritance and all in a separate file"
- Breezy theme updates to make it closer to actual Breeze in some aspects
@@ -25,11 +37,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Notifications column now cleans itself up to optimize performance when tab is left open for a long time
- 403 messaging
### Fixed
+- Fixed loader-spinner not disappearing when a status preview fails to load
- anon viewers won't get theme data saved to local storage, so admin changing default theme will have an effect for users coming back to instance.
- Single notifications left unread when hitting read on another device/tab
- Registration fixed
- Deactivation of remote accounts from frontend
- Fixed NSFW unhiding not working with videos when using one-click unhiding/displaying
+- Improved performance of anything that uses popovers (most notably statuses)
## [1.1.7 and earlier] - 2019-12-14
### Added
diff --git a/package.json b/package.json
index 5c7fa31e..542086b4 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,6 @@
"portal-vue": "^2.1.4",
"sanitize-html": "^1.13.0",
"v-click-outside": "^2.1.1",
- "v-tooltip": "^2.0.2",
"vue": "^2.5.13",
"vue-chat-scroll": "^1.2.1",
"vue-i18n": "^7.3.2",
diff --git a/src/components/account_actions/account_actions.js b/src/components/account_actions/account_actions.js
index d2153680..5d7ecf7e 100644
--- a/src/components/account_actions/account_actions.js
+++ b/src/components/account_actions/account_actions.js
@@ -1,4 +1,5 @@
import ProgressButton from '../progress_button/progress_button.vue'
+import Popover from '../popover/popover.vue'
const AccountActions = {
props: [
@@ -8,7 +9,8 @@ const AccountActions = {
return { }
},
components: {
- ProgressButton
+ ProgressButton,
+ Popover
},
methods: {
showRepeats () {
diff --git a/src/components/account_actions/account_actions.vue b/src/components/account_actions/account_actions.vue
index d3235be1..483783cf 100644
--- a/src/components/account_actions/account_actions.vue
+++ b/src/components/account_actions/account_actions.vue
@@ -1,13 +1,13 @@
<template>
<div class="account-actions">
- <v-popover
+ <Popover
trigger="click"
- class="account-tools-popover"
- :container="false"
- placement="bottom-end"
- :offset="5"
+ placement="bottom"
>
- <div slot="popover">
+ <div
+ slot="content"
+ class="account-tools-popover"
+ >
<div class="dropdown-menu">
<template v-if="user.following">
<button
@@ -51,10 +51,13 @@
</button>
</div>
</div>
- <div class="btn btn-default ellipsis-button">
+ <div
+ slot="trigger"
+ class="btn btn-default ellipsis-button"
+ >
<i class="icon-ellipsis trigger-button" />
</div>
- </v-popover>
+ </Popover>
</div>
</template>
@@ -62,7 +65,6 @@
<style lang="scss">
@import '../../_variables.scss';
-@import '../popper/popper.scss';
.account-actions {
margin: 0 .8em;
}
@@ -70,6 +72,7 @@
.account-actions button.dropdown-item {
margin-left: 0;
}
+
.account-actions .trigger-button {
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js
index b799ac9a..ae7f53be 100644
--- a/src/components/emoji_reactions/emoji_reactions.js
+++ b/src/components/emoji_reactions/emoji_reactions.js
@@ -1,20 +1,17 @@
import UserAvatar from '../user_avatar/user_avatar.vue'
+import Popover from '../popover/popover.vue'
const EMOJI_REACTION_COUNT_CUTOFF = 12
const EmojiReactions = {
name: 'EmojiReactions',
components: {
- UserAvatar
+ UserAvatar,
+ Popover
},
props: ['status'],
data: () => ({
- showAll: false,
- popperOptions: {
- modifiers: {
- preventOverflow: { padding: { top: 50 }, boundariesElement: 'viewport' }
- }
- }
+ showAll: false
}),
computed: {
tooManyReactions () {
diff --git a/src/components/emoji_reactions/emoji_reactions.vue b/src/components/emoji_reactions/emoji_reactions.vue
index b25c9716..bac4c605 100644
--- a/src/components/emoji_reactions/emoji_reactions.vue
+++ b/src/components/emoji_reactions/emoji_reactions.vue
@@ -1,15 +1,14 @@
<template>
<div class="emoji-reactions">
- <v-popover
+ <Popover
v-for="(reaction) in emojiReactions"
:key="reaction.name"
- :popper-options="popperOptions"
trigger="hover"
placement="top"
+ :offset="{ y: 5 }"
>
-
<div
- slot="popover"
+ slot="content"
class="reacted-users"
>
<div v-if="accountsForEmoji[reaction.name].length">
@@ -24,7 +23,12 @@
:compact="true"
/>
<div class="reacted-user-names">
- <span class="reacted-user-name" v-html="account.name_html" />
+ <!-- eslint-disable vue/no-v-html -->
+ <span
+ class="reacted-user-name"
+ v-html="account.name_html"
+ />
+ <!-- eslint-enable vue/no-v-html -->
<span class="reacted-user-screen-name">{{ account.screen_name }}</span>
</div>
</div>
@@ -34,6 +38,7 @@
</div>
</div>
<button
+ slot="trigger"
class="emoji-reaction btn btn-default"
:class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }"
@click="emojiOnClick(reaction.name, $event)"
@@ -42,17 +47,16 @@
<span class="reaction-emoji">{{ reaction.name }}</span>
<span>{{ reaction.count }}</span>
</button>
- </v-popover>
+ </Popover>
<a
- v-if="tooManyReactions"
- @click="toggleShowAll"
- class="emoji-reaction-expand faint"
- href='javascript:void(0)'
- >
- {{ showAll ? $t('general.show_less') : showMoreString }}
- </a>
+ v-if="tooManyReactions"
+ class="emoji-reaction-expand faint"
+ href="javascript:void(0)"
+ @click="toggleShowAll"
+ >
+ {{ showAll ? $t('general.show_less') : showMoreString }}
+ </a>
</div>
-
</template>
<script src="./emoji_reactions.js" ></script>
@@ -78,6 +82,7 @@
display: flex;
flex-direction: column;
margin-left: 0.5em;
+ min-width: 5em;
img {
width: 1em;
diff --git a/src/components/extra_buttons/extra_buttons.js b/src/components/extra_buttons/extra_buttons.js
index 5ac73e97..37485383 100644
--- a/src/components/extra_buttons/extra_buttons.js
+++ b/src/components/extra_buttons/extra_buttons.js
@@ -1,5 +1,8 @@
+import Popover from '../popover/popover.vue'
+
const ExtraButtons = {
props: [ 'status' ],
+ components: { Popover },
methods: {
deleteStatus () {
const confirmed = window.confirm(this.$t('status.delete_confirm'))
diff --git a/src/components/extra_buttons/extra_buttons.vue b/src/components/extra_buttons/extra_buttons.vue
index 746f1c91..3a7f1283 100644
--- a/src/components/extra_buttons/extra_buttons.vue
+++ b/src/components/extra_buttons/extra_buttons.vue
@@ -1,11 +1,11 @@
<template>
- <v-popover
+ <Popover
v-if="canDelete || canMute || canPin"
trigger="click"
placement="top"
class="extra-button-popover"
>
- <div slot="popover">
+ <div slot="content">
<div class="dropdown-menu">
<button
v-if="canMute && !status.thread_muted"
@@ -47,17 +47,17 @@
</button>
</div>
</div>
- <div class="button-icon">
- <i class="icon-ellipsis" />
- </div>
- </v-popover>
+ <i
+ slot="trigger"
+ class="icon-ellipsis button-icon"
+ />
+ </Popover>
</template>
<script src="./extra_buttons.js" ></script>
<style lang="scss">
@import '../../_variables.scss';
-@import '../popper/popper.scss';
.icon-ellipsis {
cursor: pointer;
diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js
index 757166ed..d4fdc53e 100644
--- a/src/components/moderation_tools/moderation_tools.js
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -1,4 +1,5 @@
import DialogModal from '../dialog_modal/dialog_modal.vue'
+import Popover from '../popover/popover.vue'
const FORCE_NSFW = 'mrf_tag:media-force-nsfw'
const STRIP_MEDIA = 'mrf_tag:media-strip'
@@ -14,7 +15,6 @@ const ModerationTools = {
],
data () {
return {
- showDropDown: false,
tags: {
FORCE_NSFW,
STRIP_MEDIA,
@@ -24,11 +24,13 @@ const ModerationTools = {
SANDBOX,
QUARANTINE
},
- showDeleteUserDialog: false
+ showDeleteUserDialog: false,
+ toggled: false
}
},
components: {
- DialogModal
+ DialogModal,
+ Popover
},
computed: {
tagsSet () {
@@ -89,6 +91,9 @@ const ModerationTools = {
window.history.back()
}
})
+ },
+ setToggled (value) {
+ this.toggled = value
}
}
}
diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue
index e78e05f1..b2d5acc5 100644
--- a/src/components/moderation_tools/moderation_tools.vue
+++ b/src/components/moderation_tools/moderation_tools.vue
@@ -1,13 +1,14 @@
<template>
<div>
- <v-popover
+ <Popover
trigger="click"
class="moderation-tools-popover"
- placement="bottom-end"
- @show="showDropDown = true"
- @hide="showDropDown = false"
+ placement="bottom"
+ :offset="{ y: 5 }"
+ @show="setToggled(true)"
+ @close="setToggled(false)"
>
- <div slot="popover">
+ <div slot="content">
<div class="dropdown-menu">
<span v-if="user.is_local">
<button
@@ -122,12 +123,13 @@
</div>
</div>
<button
+ slot="trigger"
class="btn btn-default btn-block"
- :class="{ toggled: showDropDown }"
+ :class="{ toggled }"
>
{{ $t('user_card.admin_menu.moderation') }}
</button>
- </v-popover>
+ </Popover>
<portal to="modal">
<DialogModal
v-if="showDeleteUserDialog"
@@ -160,7 +162,6 @@
<style lang="scss">
@import '../../_variables.scss';
-@import '../popper/popper.scss';
.menu-checkbox {
float: right;
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 411c0271..51875747 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -47,7 +47,7 @@
<span class="notification-details">
<div class="name-and-action">
<!-- eslint-disable vue/no-v-html -->
- <span
+ <bdi
v-if="!!notification.from_profile.name_html"
class="username"
:title="'@'+notification.from_profile.screen_name"
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index f5b13322..a8f4430f 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -81,6 +81,7 @@
.follow-text, .move-text {
padding: 0.5em 0;
+ overflow-wrap: break-word;
}
.status-el {
diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js
new file mode 100644
index 00000000..5881d266
--- /dev/null
+++ b/src/components/popover/popover.js
@@ -0,0 +1,156 @@
+
+const Popover = {
+ name: 'Popover',
+ props: {
+ // Action to trigger popover: either 'hover' or 'click'
+ trigger: String,
+ // Either 'top' or 'bottom'
+ placement: String,
+ // Takes object with properties 'x' and 'y', values of these can be
+ // 'container' for using offsetParent as boundaries for either axis
+ // or 'viewport'
+ boundTo: Object,
+ // Takes a top/bottom/left/right object, how much space to leave
+ // between boundary and popover element
+ margin: Object,
+ // Takes a x/y object and tells how many pixels to offset from
+ // anchor point on either axis
+ offset: Object,
+ // Additional styles you may want for the popover container
+ popoverClass: String
+ },
+ data () {
+ return {
+ hidden: true,
+ styles: { opacity: 0 },
+ oldSize: { width: 0, height: 0 }
+ }
+ },
+ methods: {
+ updateStyles () {
+ if (this.hidden) {
+ this.styles = {
+ opacity: 0
+ }
+ return
+ }
+
+ // Popover will be anchored around this element, trigger ref is the container, so
+ // its children are what are inside the slot. Expect only one slot="trigger".
+ const anchorEl = (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el
+ const screenBox = anchorEl.getBoundingClientRect()
+ // Screen position of the origin point for popover
+ const origin = { x: screenBox.left + screenBox.width * 0.5, y: screenBox.top }
+ const content = this.$refs.content
+ // Minor optimization, don't call a slow reflow call if we don't have to
+ const parentBounds = this.boundTo &&
+ (this.boundTo.x === 'container' || this.boundTo.y === 'container') &&
+ this.$el.offsetParent.getBoundingClientRect()
+ const margin = this.margin || {}
+
+ // What are the screen bounds for the popover? Viewport vs container
+ // when using viewport, using default margin values to dodge the navbar
+ const xBounds = this.boundTo && this.boundTo.x === 'container' ? {
+ min: parentBounds.left + (margin.left || 0),
+ max: parentBounds.right - (margin.right || 0)
+ } : {
+ min: 0 + (margin.left || 10),
+ max: window.innerWidth - (margin.right || 10)
+ }
+
+ const yBounds = this.boundTo && this.boundTo.y === 'container' ? {
+ min: parentBounds.top + (margin.top || 0),
+ max: parentBounds.bottom - (margin.bottom || 0)
+ } : {
+ min: 0 + (margin.top || 50),
+ max: window.innerHeight - (margin.bottom || 5)
+ }
+
+ let horizOffset = 0
+
+ // If overflowing from left, move it so that it doesn't
+ if ((origin.x - content.offsetWidth * 0.5) < xBounds.min) {
+ horizOffset += -(origin.x - content.offsetWidth * 0.5) + xBounds.min
+ }
+
+ // If overflowing from right, move it so that it doesn't
+ if ((origin.x + horizOffset + content.offsetWidth * 0.5) > xBounds.max) {
+ horizOffset -= (origin.x + horizOffset + content.offsetWidth * 0.5) - xBounds.max
+ }
+
+ // Default to whatever user wished with placement prop
+ let usingTop = this.placement !== 'bottom'
+
+ // Handle special cases, first force to displaying on top if there's not space on bottom,
+ // regardless of what placement value was. Then check if there's not space on top, and
+ // force to bottom, again regardless of what placement value was.
+ if (origin.y + content.offsetHeight > yBounds.max) usingTop = true
+ if (origin.y - content.offsetHeight < yBounds.min) usingTop = false
+
+ const yOffset = (this.offset && this.offset.y) || 0
+ const translateY = usingTop
+ ? -anchorEl.offsetHeight - yOffset - content.offsetHeight
+ : yOffset
+
+ const xOffset = (this.offset && this.offset.x) || 0
+ const translateX = (anchorEl.offsetWidth * 0.5) - content.offsetWidth * 0.5 + horizOffset + xOffset
+
+ // Note, separate translateX and translateY avoids blurry text on chromium,
+ // single translate or translate3d resulted in blurry text.
+ this.styles = {
+ opacity: 1,
+ transform: `translateX(${Math.floor(translateX)}px) translateY(${Math.floor(translateY)}px)`
+ }
+ },
+ showPopover () {
+ if (this.hidden) this.$emit('show')
+ this.hidden = false
+ this.$nextTick(this.updateStyles)
+ },
+ hidePopover () {
+ if (!this.hidden) this.$emit('close')
+ this.hidden = true
+ this.styles = { opacity: 0 }
+ },
+ onMouseenter (e) {
+ if (this.trigger === 'hover') this.showPopover()
+ },
+ onMouseleave (e) {
+ if (this.trigger === 'hover') this.hidePopover()
+ },
+ onClick (e) {
+ if (this.trigger === 'click') {
+ if (this.hidden) {
+ this.showPopover()
+ } else {
+ this.hidePopover()
+ }
+ }
+ },
+ onClickOutside (e) {
+ if (this.hidden) return
+ if (this.$el.contains(e.target)) return
+ this.hidePopover()
+ }
+ },
+ updated () {
+ // Monitor changes to content size, update styles only when content sizes have changed,
+ // that should be the only time we need to move the popover box if we don't care about scroll
+ // or resize
+ const content = this.$refs.content
+ if (!content) return
+ if (this.oldSize.width !== content.offsetWidth || this.oldSize.height !== content.offsetHeight) {
+ this.updateStyles()
+ this.oldSize = { width: content.offsetWidth, height: content.offsetHeight }
+ }
+ },
+ created () {
+ document.addEventListener('click', this.onClickOutside)
+ },
+ destroyed () {
+ document.removeEventListener('click', this.onClickOutside)
+ this.hidePopover()
+ }
+}
+
+export default Popover
diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue
new file mode 100644
index 00000000..a271cb1b
--- /dev/null
+++ b/src/components/popover/popover.vue
@@ -0,0 +1,118 @@
+<template>
+ <div
+ @mouseenter="onMouseenter"
+ @mouseleave="onMouseleave"
+ >
+ <div
+ ref="trigger"
+ @click="onClick"
+ >
+ <slot name="trigger" />
+ </div>
+ <div
+ v-if="!hidden"
+ ref="content"
+ :style="styles"
+ class="popover"
+ :class="popoverClass"
+ >
+ <slot
+ name="content"
+ class="popover-inner"
+ :close="hidePopover"
+ />
+ </div>
+ </div>
+</template>
+
+<script src="./popover.js" />
+
+<style lang=scss>
+@import '../../_variables.scss';
+
+.popover {
+ z-index: 8;
+ position: absolute;
+ min-width: 0;
+ transition: opacity 0.3s;
+
+ box-shadow: 1px 1px 4px rgba(0,0,0,.6);
+ box-shadow: var(--panelShadow);
+ border-radius: $fallback--btnRadius;
+ border-radius: var(--btnRadius, $fallback--btnRadius);
+
+ background-color: $fallback--bg;
+ background-color: var(--popover, $fallback--bg);
+ color: $fallback--text;
+ color: var(--popoverText, $fallback--text);
+ --faint: var(--popoverFaintText, $fallback--faint);
+ --faintLink: var(--popoverFaintLink, $fallback--faint);
+ --lightText: var(--popoverLightText, $fallback--lightText);
+ --postLink: var(--popoverPostLink, $fallback--link);
+ --postFaintLink: var(--popoverPostFaintLink, $fallback--link);
+ --icon: var(--popoverIcon, $fallback--icon);
+}
+
+.dropdown-menu {
+ display: block;
+ padding: .5rem 0;
+ font-size: 1rem;
+ text-align: left;
+ list-style: none;
+ max-width: 100vw;
+ z-index: 10;
+ white-space: nowrap;
+
+ .dropdown-divider {
+ height: 0;
+ margin: .5rem 0;
+ overflow: hidden;
+ border-top: 1px solid $fallback--border;
+ border-top: 1px solid var(--border, $fallback--border);
+ }
+
+ .dropdown-item {
+ line-height: 21px;
+ margin-right: 5px;
+ overflow: auto;
+ display: block;
+ padding: .25rem 1.0rem .25rem 1.5rem;
+ clear: both;
+ font-weight: 400;
+ text-align: inherit;
+ white-space: nowrap;
+ border: none;
+ border-radius: 0px;
+ background-color: transparent;
+ box-shadow: none;
+ width: 100%;
+ height: 100%;
+
+ --btnText: var(--popoverText, $fallback--text);
+
+ &-icon {
+ padding-left: 0.5rem;
+
+ i {
+ margin-right: 0.25rem;
+ color: var(--menuPopoverIcon, $fallback--icon)
+ }
+ }
+
+ &:active, &:hover {
+ background-color: $fallback--lightBg;
+ background-color: var(--selectedMenuPopover, $fallback--lightBg);
+ color: $fallback--link;
+ color: var(--selectedMenuPopoverText, $fallback--link);
+ --faint: var(--selectedMenuPopoverFaintText, $fallback--faint);
+ --faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint);
+ --lightText: var(--selectedMenuPopoverLightText, $fallback--lightText);
+ --icon: var(--selectedMenuPopoverIcon, $fallback--icon);
+ i {
+ color: var(--selectedMenuPopoverIcon, $fallback--icon);
+ }
+ }
+
+ }
+}
+</style>
diff --git a/src/components/popper/popper.scss b/src/components/popper/popper.scss
deleted file mode 100644
index 99b7e6fc..00000000
--- a/src/components/popper/popper.scss
+++ /dev/null
@@ -1,164 +0,0 @@
-@import '../../_variables.scss';
-
-.tooltip.popover {
- z-index: 8;
-
- .popover-inner {
- box-shadow: 1px 1px 4px rgba(0,0,0,.6);
- box-shadow: var(--panelShadow);
- border-radius: $fallback--btnRadius;
- border-radius: var(--btnRadius, $fallback--btnRadius);
- background-color: $fallback--bg;
- background-color: var(--popover, $fallback--bg);
- color: $fallback--text;
- color: var(--popoverText, $fallback--text);
- --faint: var(--popoverFaintText, $fallback--faint);
- --faintLink: var(--popoverFaintLink, $fallback--faint);
- --lightText: var(--popoverLightText, $fallback--lightText);
- --postLink: var(--popoverPostLink, $fallback--link);
- --postFaintLink: var(--popoverPostFaintLink, $fallback--link);
- --icon: var(--popoverIcon, $fallback--icon);
- }
-
- .popover-arrow {
- width: 0;
- height: 0;
- border-style: solid;
- position: absolute;
- margin: 5px;
- border-color: $fallback--bg;
- border-color: var(--bg, $fallback--bg);
- }
-
- &[x-placement^="top"] {
- margin-bottom: 5px;
-
- .popover-arrow {
- border-width: 5px 5px 0 5px;
- border-left-color: transparent !important;
- border-right-color: transparent !important;
- border-bottom-color: transparent !important;
- bottom: -4px;
- left: calc(50% - 5px);
- margin-top: 0;
- margin-bottom: 0;
- }
- }
-
- &[x-placement^="bottom"] {
- margin-top: 5px;
-
- .popover-arrow {
- border-width: 0 5px 5px 5px;
- border-left-color: transparent !important;
- border-right-color: transparent !important;
- border-top-color: transparent !important;
- top: -4px;
- left: calc(50% - 5px);
- margin-top: 0;
- margin-bottom: 0;
- }
- }
-
- &[x-placement^="right"] {
- margin-left: 5px;
-
- .popover-arrow {
- border-width: 5px 5px 5px 0;
- border-left-color: transparent !important;
- border-top-color: transparent !important;
- border-bottom-color: transparent !important;
- left: -4px;
- top: calc(50% - 5px);
- margin-left: 0;
- margin-right: 0;
- }
- }
-
- &[x-placement^="left"] {
- margin-right: 5px;
-
- .popover-arrow {
- border-width: 5px 0 5px 5px;
- border-top-color: transparent !important;
- border-right-color: transparent !important;
- border-bottom-color: transparent !important;
- right: -4px;
- top: calc(50% - 5px);
- margin-left: 0;
- margin-right: 0;
- }
- }
-
- &[aria-hidden='true'] {
- visibility: hidden;
- opacity: 0;
- transition: opacity .15s, visibility .15s;
- }
-
- &[aria-hidden='false'] {
- visibility: visible;
- opacity: 1;
- transition: opacity .15s;
- }
-}
-
-.dropdown-menu {
- display: block;
- padding: .5rem 0;
- font-size: 1rem;
- text-align: left;
- list-style: none;
- max-width: 100vw;
- z-index: 10;
-
- .dropdown-divider {
- height: 0;
- margin: .5rem 0;
- overflow: hidden;
- border-top: 1px solid $fallback--border;
- border-top: 1px solid var(--border, $fallback--border);
- }
-
- .dropdown-item {
- line-height: 21px;
- margin-right: 5px;
- overflow: auto;
- display: block;
- padding: .25rem 1.0rem .25rem 1.5rem;
- clear: both;
- font-weight: 400;
- text-align: inherit;
- white-space: normal;
- border: none;
- border-radius: 0px;
- background-color: transparent;
- box-shadow: none;
- width: 100%;
- height: 100%;
-
- --btnText: var(--popoverText, $fallback--text);
-
- &-icon {
- padding-left: 0.5rem;
-
- i {
- margin-right: 0.25rem;
- }
- }
-
- &:active, &:hover {
- background-color: $fallback--lightBg;
- background-color: var(--selectedMenuPopover, $fallback--lightBg);
- color: $fallback--link;
- color: var(--selectedMenuPopoverText, $fallback--link);
- --faint: var(--selectedMenuPopoverFaintText, $fallback--faint);
- --faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint);
- --lightText: var(--selectedMenuPopoverLightText, $fallback--lightText);
- --icon: var(--selectedMenuPopoverIcon, $fallback--icon);
- i {
- color: var(--selectedMenuPopoverIcon, $fallback--icon);
- }
- }
- }
-}
diff --git a/src/components/react_button/react_button.js b/src/components/react_button/react_button.js
index a6cf5b94..19949563 100644
--- a/src/components/react_button/react_button.js
+++ b/src/components/react_button/react_button.js
@@ -1,34 +1,25 @@
+import Popover from '../popover/popover.vue'
import { mapGetters } from 'vuex'
const ReactButton = {
props: ['status', 'loggedIn'],
data () {
return {
- showTooltip: false,
- filterWord: '',
- popperOptions: {
- modifiers: {
- preventOverflow: { padding: { top: 50 }, boundariesElement: 'viewport' }
- }
- }
+ filterWord: ''
}
},
+ components: {
+ Popover
+ },
methods: {
- openReactionSelect () {
- this.showTooltip = true
- this.filterWord = ''
- },
- closeReactionSelect () {
- this.showTooltip = false
- },
- addReaction (event, emoji) {
+ addReaction (event, emoji, close) {
const existingReaction = this.status.emoji_reactions.find(r => r.name === emoji)
if (existingReaction && existingReaction.me) {
this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })
} else {
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
}
- this.closeReactionSelect()
+ close()
}
},
computed: {
diff --git a/src/components/react_button/react_button.vue b/src/components/react_button/react_button.vue
index fb43ebaf..ab4b4fcd 100644
--- a/src/components/react_button/react_button.vue
+++ b/src/components/react_button/react_button.vue
@@ -1,13 +1,14 @@
<template>
- <v-popover
- :popper-options="popperOptions"
- :open="showTooltip"
- trigger="manual"
+ <Popover
+ trigger="click"
placement="top"
+ :offset="{ y: 5 }"
class="react-button-popover"
- @hide="closeReactionSelect"
>
- <div slot="popover">
+ <div
+ slot="content"
+ slot-scope="{close}"
+ >
<div class="reaction-picker-filter">
<input
v-model="filterWord"
@@ -19,7 +20,7 @@
v-for="emoji in commonEmojis"
:key="emoji"
class="emoji-button"
- @click="addReaction($event, emoji)"
+ @click="addReaction($event, emoji, close)"
>
{{ emoji }}
</span>
@@ -28,23 +29,20 @@
v-for="(emoji, key) in emojis"
:key="key"
class="emoji-button"
- @click="addReaction($event, emoji.replacement)"
+ @click="addReaction($event, emoji.replacement, close)"
>
{{ emoji.replacement }}
</span>
<div class="reaction-bottom-fader" />
</div>
</div>
- <div
+ <i
v-if="loggedIn"
- @click.prevent="openReactionSelect"
- >
- <i
- class="icon-smile button-icon add-reaction-button"
- :title="$t('tool_tip.add_reaction')"
- />
- </div>
- </v-popover>
+ slot="trigger"
+ class="icon-smile button-icon add-reaction-button"
+ :title="$t('tool_tip.add_reaction')"
+ />
+ </Popover>
</template>
<script src="./react_button.js" ></script>
diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue
index fdbda007..a83ca1e5 100644
--- a/src/components/registration/registration.vue
+++ b/src/components/registration/registration.vue
@@ -187,6 +187,9 @@
class="form-control"
type="text"
autocomplete="off"
+ autocorrect="off"
+ autocapitalize="off"
+ spellcheck="false"
>
</template>
</div>
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 76b038d9..ca295640 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -177,6 +177,8 @@
<StatusPopover
v-if="!isPreview"
:status-id="status.in_reply_to_status_id"
+ class="reply-to-popover"
+ style="min-width: 0"
>
<a
class="reply-to"
@@ -572,11 +574,10 @@ $status-margin: 0.75em;
align-items: stretch;
> .reply-to-and-accountname > a {
+ overflow: hidden;
max-width: 100%;
text-overflow: ellipsis;
- overflow: hidden;
white-space: nowrap;
- display: inline-block;
word-break: break-all;
}
}
@@ -585,7 +586,6 @@ $status-margin: 0.75em;
display: flex;
height: 18px;
margin-right: 0.5em;
- overflow: hidden;
max-width: 100%;
.icon-reply {
transform: scaleX(-1);
@@ -596,6 +596,10 @@ $status-margin: 0.75em;
display: flex;
}
+ .reply-to-popover {
+ min-width: 0;
+ }
+
.reply-to {
display: flex;
}
@@ -603,6 +607,7 @@ $status-margin: 0.75em;
.reply-to-text {
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
margin: 0 0.4em 0 0.2em;
}
diff --git a/src/components/status_popover/status_popover.js b/src/components/status_popover/status_popover.js
index 19f16bd9..159132a9 100644
--- a/src/components/status_popover/status_popover.js
+++ b/src/components/status_popover/status_popover.js
@@ -7,11 +7,7 @@ const StatusPopover = {
],
data () {
return {
- popperOptions: {
- modifiers: {
- preventOverflow: { padding: { top: 50 }, boundariesElement: 'viewport' }
- }
- }
+ error: false
}
},
computed: {
@@ -20,12 +16,15 @@ const StatusPopover = {
}
},
components: {
- Status: () => import('../status/status.vue')
+ Status: () => import('../status/status.vue'),
+ Popover: () => import('../popover/popover.vue')
},
methods: {
enter () {
if (!this.status) {
this.$store.dispatch('fetchStatus', this.statusId)
+ .then(data => (this.error = false))
+ .catch(e => (this.error = true))
}
}
}
diff --git a/src/components/status_popover/status_popover.vue b/src/components/status_popover/status_popover.vue
index eacf4c06..f5948207 100644
--- a/src/components/status_popover/status_popover.vue
+++ b/src/components/status_popover/status_popover.vue
@@ -1,11 +1,16 @@
<template>
- <v-popover
+ <Popover
+ trigger="hover"
popover-class="status-popover"
- placement="top-start"
- :popper-options="popperOptions"
- @show="enter()"
+ :bound-to="{ x: 'container' }"
+ @show="enter"
>
- <template slot="popover">
+ <template slot="trigger">
+ <slot />
+ </template>
+ <div
+ slot="content"
+ >
<Status
v-if="status"
:is-preview="true"
@@ -13,15 +18,19 @@
:compact="true"
/>
<div
+ v-else-if="error"
+ class="status-preview-no-content faint"
+ >
+ {{ $t('status.status_unavailable') }}
+ </div>
+ <div
v-else
- class="status-preview-loading"
+ class="status-preview-no-content"
>
<i class="icon-spin4 animate-spin" />
</div>
- </template>
-
- <slot />
- </v-popover>
+ </div>
+ </Popover>
</template>
<script src="./status_popover.js" ></script>
@@ -29,50 +38,25 @@
<style lang="scss">
@import '../../_variables.scss';
-.tooltip.popover.status-popover {
+.status-popover {
font-size: 1rem;
min-width: 15em;
max-width: 95%;
- margin-left: 0.5em;
- .popover-inner {
- border-color: $fallback--border;
- border-color: var(--border, $fallback--border);
- border-style: solid;
- border-width: 1px;
- border-radius: $fallback--tooltipRadius;
- border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
- box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
- box-shadow: var(--popupShadow);
- }
-
- .popover-arrow::before {
- position: absolute;
- content: '';
- left: -7px;
- border: solid 7px transparent;
- z-index: -1;
- }
-
- &[x-placement^="bottom-start"] .popover-arrow::before {
- top: -2px;
- border-top-width: 0;
- border-bottom-color: $fallback--border;
- border-bottom-color: var(--border, $fallback--border);
- }
-
- &[x-placement^="top-start"] .popover-arrow::before {
- bottom: -2px;
- border-bottom-width: 0;
- border-top-color: $fallback--border;
- border-top-color: var(--border, $fallback--border);
- }
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: $fallback--tooltipRadius;
+ border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
+ box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
+ box-shadow: var(--popupShadow);
.status-el.status-el {
border: none;
}
- .status-preview-loading {
+ .status-preview-no-content {
padding: 1em;
text-align: center;
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 82acc1ab..54d0608e 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -615,7 +615,8 @@
"reply_to": "Reply to",
"replies_list": "Replies:",
"mute_conversation": "Mute conversation",
- "unmute_conversation": "Unmute conversation"
+ "unmute_conversation": "Unmute conversation",
+ "status_unavailable": "Status unavailable"
},
"user_card": {
"approve": "Approve",
diff --git a/src/i18n/fi.json b/src/i18n/fi.json
index ac8b2ac9..926e6087 100644
--- a/src/i18n/fi.json
+++ b/src/i18n/fi.json
@@ -289,7 +289,8 @@
"reply_to": "Vastaus",
"replies_list": "Vastaukset:",
"mute_conversation": "Hiljennä keskustelu",
- "unmute_conversation": "Poista hiljennys"
+ "unmute_conversation": "Poista hiljennys",
+ "status_unavailable": "Viesti ei saatavissa"
},
"user_card": {
"approve": "Hyväksy",
diff --git a/src/i18n/pl.json b/src/i18n/pl.json
index 51cadfb6..4a4b1e31 100644
--- a/src/i18n/pl.json
+++ b/src/i18n/pl.json
@@ -1,7 +1,47 @@
{
+ "about": {
+ "mrf": {
+ "federation": "Federacja",
+ "keyword": {
+ "keyword_policies": "Zasady słów kluczowych",
+ "ftl_removal": "Usunięcie z \"Całej znanej sieci\"",
+ "reject": "Odrzucanie",
+ "replace": "Zastąpienie",
+ "is_replaced_by": "→"
+ },
+ "mrf_policies": "Włączone zasady MRF",
+ "mrf_policies_desc": "Zasady MRF zmieniają zachowanie federowania instancji. Następujące zasady są włączone:",
+ "simple": {
+ "simple_policies": "Zasady specyficzne dla instancji",
+ "accept": "Akceptowanie",
+ "accept_desc": "Ta instancja akceptuje tylko posty z wymienionych instancji:",
+ "reject": "Odrzucanie",
+ "reject_desc": "Ta instancja odrzuca posty z wymienionych instancji:",
+ "quarantine": "Kwarantanna",
+ "quarantine_desc": "Ta instancja wysyła tylko publiczne posty do wymienionych instancji:",
+ "ftl_removal": "Usunięcie z \"Całej znanej sieci\"",
+ "ftl_removal_desc": "Ta instancja usuwa te instancje z \"Całej znanej sieci\"",
+ "media_removal": "Usuwanie multimediów",
+ "media_removal_desc": "Ta instancja usuwa multimedia z postów od wymienionych instancji:",
+ "media_nsfw": "Multimedia ustawione jako wrażliwe",
+ "media_nsfw_desc": "Ta instancja wymusza, by multimedia z wymienionych instancji były ustawione jako wrażliwe:"
+ }
+ },
+ "staff": "Obsługa"
+ },
"chat": {
"title": "Czat"
},
+ "domain_mute_card": {
+ "mute": "Wycisz",
+ "mute_progress": "Wyciszam...",
+ "unmute": "Odcisz",
+ "unmute_progress": "Odciszam..."
+ },
+ "exporter": {
+ "export": "Eksportuj",
+ "processing": "Przetwarzam, za chwilę zostaniesz zapytany o ściągnięcie pliku"
+ },
"features_panel": {
"chat": "Czat",
"gopher": "Gopher",
@@ -20,7 +60,15 @@
"submit": "Wyślij",
"more": "Więcej",
"generic_error": "Wystąpił błąd",
- "optional": "nieobowiązkowe"
+ "optional": "nieobowiązkowe",
+ "show_more": "Pokaż więcej",
+ "show_less": "Pokaż mniej",
+ "dismiss": "Odrzuć",
+ "cancel": "Anuluj",
+ "disable": "Wyłącz",
+ "enable": "Włącz",
+ "confirm": "Potwierdź",
+ "verify": "Zweryfikuj"
},
"image_cropper": {
"crop_picture": "Przytnij obrazek",
@@ -28,6 +76,11 @@
"save_without_cropping": "Zapisz bez przycinania",
"cancel": "Anuluj"
},
+ "importer": {
+ "submit": "Wyślij",
+ "success": "Zaimportowano pomyślnie",
+ "error": "Wystąpił błąd podczas importowania pliku."
+ },
"login": {
"login": "Zaloguj",
"description": "Zaloguj używając OAuth",
@@ -36,7 +89,15 @@
"placeholder": "n.p. lain",
"register": "Zarejestruj",
"username": "Użytkownik",
- "hint": "Zaloguj się, aby dołączyć do dyskusji"
+ "hint": "Zaloguj się, aby dołączyć do dyskusji",
+ "authentication_code": "Kod weryfikacyjny",
+ "enter_recovery_code": "Wprowadź kod zapasowy",
+ "enter_two_factor_code": "Wprowadź kod weryfikacyjny",
+ "recovery_code": "Kod zapasowy",
+ "heading" : {
+ "totp" : "Weryfikacja dwuetapowa",
+ "recovery" : "Zapasowa weryfikacja dwuetapowa"
+ }
},
"media_modal": {
"previous": "Poprzednie",
@@ -44,15 +105,18 @@
},
"nav": {
"about": "O nas",
+ "administration": "Administracja",
"back": "Wróć",
"chat": "Lokalny czat",
"friend_requests": "Prośby o możliwość obserwacji",
"mentions": "Wzmianki",
+ "interactions": "Interakcje",
"dms": "Wiadomości prywatne",
"public_tl": "Publiczna oś czasu",
"timeline": "Oś czasu",
"twkn": "Cała znana sieć",
"user_search": "Wyszukiwanie użytkowników",
+ "search": "Wyszukiwanie",
"who_to_follow": "Sugestie obserwacji",
"preferences": "Preferencje"
},
@@ -64,7 +128,40 @@
"notifications": "Powiadomienia",
"read": "Przeczytane!",
"repeated_you": "powtórzył(-a) twój status",
- "no_more_notifications": "Nie masz więcej powiadomień"
+ "no_more_notifications": "Nie masz więcej powiadomień",
+ "migrated_to": "wyemigrował do",
+ "reacted_with": "zareagował z {0}"
+ },
+ "polls": {
+ "add_poll": "Dodaj ankietę",
+ "add_option": "Dodaj opcję",
+ "option": "Opcja",
+ "votes": "głosów",
+ "vote": "Głosuj",
+ "type": "Typ ankiety",
+ "single_choice": "jednokrotnego wyboru",
+ "multiple_choices": "wielokrotnego wyboru",
+ "expiry": "Czas trwania ankiety",
+ "expires_in": "Ankieta kończy się za{0}",
+ "expired": "Ankieta skończyła się {0} temu",
+ "not_enough_options": "Zbyt mało unikalnych opcji w ankiecie"
+ },
+ "emoji": {
+ "stickers": "Naklejki",
+ "emoji": "Emoji",
+ "keep_open": "Zostaw selektor otwarty",
+ "search_emoji": "Wyszukaj emoji",
+ "add_emoji": "Wstaw emoji",
+ "custom": "Niestandardowe emoji",
+ "unicode": "Emoji unicode",
+ "load_all_hint": "Załadowano pierwsze {saneAmount} emoji, Załadowanie wszystkich emoji może spowodować problemy z wydajnością.",
+ "load_all": "Ładuję wszystkie {emojiAmount} emoji"
+ },
+ "interactions": {
+ "favs_repeats": "Powtórzenia i ulubione",
+ "follows": "Nowi obserwujący",
+ "moves": "Użytkownik migruje",
+ "load_older": "Załaduj starsze interakcje"
},
"post_status": {
"new_status": "Dodaj nowy status",
@@ -79,8 +176,14 @@
},
"content_warning": "Temat (nieobowiązkowy)",
"default": "Właśnie wróciłem z kościoła",
- "direct_warning": "Ten wpis zobaczą tylko osoby, o których wspomniałeś(-aś).",
+ "direct_warning_to_all": "Ten wpis zobaczą wszystkie osoby, o których wspomniałeś(-aś).",
+ "direct_warning_to_first_only": "Ten wpis zobaczą tylko te osoby, o których wspomniałeś(-aś) na początku wiadomości.",
"posting": "Wysyłanie",
+ "scope_notice": {
+ "public": "Ten post będzie widoczny dla każdego",
+ "private": "Ten post będzie widoczny tylko dla twoich obserwujących",
+ "unlisted": "Ten post nie będzie widoczny na publicznej osi czasu i całej znanej sieci"
+ },
"scope": {
"direct": "Bezpośredni – Tylko dla wspomnianych użytkowników",
"private": "Tylko dla obserwujących – Umieść dla osób, które cię obserwują",
@@ -109,8 +212,40 @@
"password_confirmation_match": "musi być takie jak hasło"
}
},
+ "remote_user_resolver": {
+ "remote_user_resolver": "Wyszukiwarka użytkowników nietutejszych",
+ "searching_for": "Szukam",
+ "error": "Nie znaleziono."
+ },
+ "selectable_list": {
+ "select_all": "Zaznacz wszystko"
+ },
"settings": {
"app_name": "Nazwa aplikacji",
+ "security": "Bezpieczeństwo",
+ "enter_current_password_to_confirm": "Wprowadź obecne hasło, by potwierdzić twoją tożsamość",
+ "mfa": {
+ "otp" : "OTP",
+ "setup_otp" : "Ustaw OTP",
+ "wait_pre_setup_otp" : "początkowe ustawianie OTP",
+ "confirm_and_enable" : "Potwierdź i włącz OTP",
+ "title": "Weryfikacja dwuetapowa",
+ "generate_new_recovery_codes" : "Wygeneruj nowe kody zapasowe",
+ "warning_of_generate_new_codes" : "Po tym gdy generujesz nowe kody zapasowe, stare przestaną działać.",
+ "recovery_codes" : "Kody zapasowe.",
+ "waiting_a_recovery_codes": "Otrzymuję kody zapasowe...",
+ "recovery_codes_warning" : "Spisz kody na kartce papieru, albo zapisz je w bezpiecznym miejscu - inaczej nie zobaczysz ich już nigdy. Jeśli stracisz dostęp do twojej aplikacji 2FA i kodów zapasowych, nie będziesz miał dostępu do swojego konta.",
+ "authentication_methods" : "Metody weryfikacji",
+ "scan": {
+ "title": "Skanuj",
+ "desc": "Zeskanuj ten kod QR używając twojej aplikacji 2FA albo wpisz ten klucz:",
+ "secret_code": "Klucz"
+ },
+ "verify": {
+ "desc": "By włączyć weryfikację dwuetapową, wpisz kod z twojej aplikacji 2FA:"
+ }
+ },
+ "allow_following_move": "Zezwalaj na automatyczną obserwację gdy obserwowane konto migruje",
"attachmentRadius": "Załączniki",
"attachments": "Załączniki",
"autoload": "Włącz automatyczne ładowanie po przewinięciu do końca strony",
@@ -119,12 +254,20 @@
"avatarRadius": "Awatary",
"background": "Tło",
"bio": "Bio",
+ "block_export": "Eksport blokad",
+ "block_export_button": "Eksportuj twoje blokady do pliku .csv",
+ "block_import": "Import blokad",
+ "block_import_error": "Wystąpił błąd podczas importowania blokad",
+ "blocks_imported": "Zaimportowano blokady, przetwarzanie może zająć trochę czasu.",
"blocks_tab": "Bloki",
"btnRadius": "Przyciski",
"cBlue": "Niebieski (odpowiedz, obserwuj)",
"cGreen": "Zielony (powtórzenia)",
"cOrange": "Pomarańczowy (ulubione)",
"cRed": "Czerwony (anuluj)",
+ "change_email": "Zmień email",
+ "change_email_error": "Wystąpił problem podczas zmiany emaila.",
+ "changed_email": "Pomyślnie zmieniono email!",
"change_password": "Zmień hasło",
"change_password_error": "Podczas zmiany hasła wystąpił problem.",
"changed_password": "Pomyślnie zmieniono hasło!",
@@ -140,16 +283,20 @@
"delete_account_description": "Trwale usuń konto i wszystkie posty.",
"delete_account_error": "Wystąpił problem z usuwaniem twojego konta. Jeżeli problem powtarza się, poinformuj administratora swojej instancji.",
"delete_account_instructions": "Wprowadź swoje hasło w poniższe pole aby potwierdzić usunięcie konta.",
+ "discoverable": "Zezwól na odkrywanie tego konta w wynikach wyszukiwania i innych usługa.",
+ "domain_mutes": "Domeny",
"avatar_size_instruction": "Zalecany minimalny rozmiar awatarów to 150x150 pikseli.",
+ "pad_emoji": "Dodaj odstęp z obu stron emoji podczas dodawania selektorem",
+ "emoji_reactions_on_timeline": "Pokaż reakcje emoji na osi czasu",
"export_theme": "Zapisz motyw",
"filtering": "Filtrowanie",
"filtering_explanation": "Wszystkie statusy zawierające te słowa będą wyciszone. Jedno słowo na linijkę.",
"follow_export": "Eksport obserwowanych",
"follow_export_button": "Eksportuj swoją listę obserwowanych do pliku CSV",
- "follow_export_processing": "Przetwarzanie, wkrótce twój plik zacznie się ściągać.",
"follow_import": "Import obserwowanych",
"follow_import_error": "Błąd przy importowaniu obserwowanych",
"follows_imported": "Obserwowani zaimportowani! Przetwarzanie może trochę potrwać.",
+ "accent": "Akcent",
"foreground": "Pierwszy plan",
"general": "Ogólne",
"hide_attachments_in_convo": "Ukrywaj załączniki w rozmowach",
@@ -162,6 +309,7 @@
"hide_post_stats": "Ukrywaj statysyki postów (np. liczbę polubień)",
"hide_user_stats": "Ukrywaj statysyki użytkowników (np. liczbę obserwujących)",
"hide_filtered_statuses": "Ukrywaj filtrowane statusy",
+ "import_blocks_from_a_csv_file": "Importuj blokady z pliku CSV",
"import_followers_from_a_csv_file": "Importuj obserwowanych z pliku CSV",
"import_theme": "Załaduj motyw",
"inputRadius": "Pola tekstowe",
@@ -181,17 +329,22 @@
"use_contain_fit": "Nie przycinaj załączników na miniaturach",
"name": "Imię",
"name_bio": "Imię i bio",
+ "new_email": "Nowy email",
"new_password": "Nowe hasło",
"notification_visibility": "Rodzaje powiadomień do wyświetlania",
"notification_visibility_follows": "Obserwacje",
"notification_visibility_likes": "Ulubione",
"notification_visibility_mentions": "Wzmianki",
"notification_visibility_repeats": "Powtórzenia",
+ "notification_visibility_moves": "Użytkownik migruje",
+ "notification_visibility_emoji_reactions": "Reakcje",
"no_rich_text_description": "Usuwaj formatowanie ze wszystkich postów",
"no_blocks": "Bez blokad",
"no_mutes": "Bez wyciszeń",
"hide_follows_description": "Nie pokazuj kogo obserwuję",
"hide_followers_description": "Nie pokazuj kto mnie obserwuje",
+ "hide_follows_count_description": "Nie pokazuj licznika obserwowanych",
+ "hide_followers_count_description": "Nie pokazuj licznika obserwujących",
"show_admin_badge": "Pokazuj odznakę Administrator na moim profilu",
"show_moderator_badge": "Pokazuj odznakę Moderator na moim profilu",
"nsfw_clickthrough": "Włącz domyślne ukrywanie załączników o treści nieprzyzwoitej (NSFW)",
@@ -212,10 +365,14 @@
"reply_visibility_all": "Pokazuj wszystkie odpowiedzi",
"reply_visibility_following": "Pokazuj tylko odpowiedzi skierowane do mnie i osób które obserwuję",
"reply_visibility_self": "Pokazuj tylko odpowiedzi skierowane do mnie",
+ "autohide_floating_post_button": "Ukryj automatycznie przycisk \"Nowy post\" (mobile)",
"saving_err": "Nie udało się zapisać ustawień",
"saving_ok": "Zapisano ustawienia",
+ "search_user_to_block": "Wyszukaj kogo chcesz zablokować",
+ "search_user_to_mute": "Wyszukaj kogo chcesz wyciszyć",
"security_tab": "Bezpieczeństwo",
"scope_copy": "Kopiuj zakres podczas odpowiadania (DM-y zawsze są kopiowane)",
+ "minimal_scopes_mode": "Zminimalizuj opcje wyboru zakresu postów",
"set_new_avatar": "Ustaw nowy awatar",
"set_new_profile_background": "Ustaw nowe tło profilu",
"set_new_profile_banner": "Ustaw nowy banner profilu",
@@ -228,19 +385,32 @@
"post_status_content_type": "Post status content type",
"stop_gifs": "Odtwarzaj GIFy po najechaniu kursorem",
"streaming": "Włącz automatycznie strumieniowanie nowych postów gdy jesteś na początku strony",
+ "user_mutes": "Users",
+ "useStreamingApi": "Otrzymuj posty i powiadomienia w czasie rzeczywistym",
+ "useStreamingApiWarning": "(Niezalecane, eksperymentalne, pomija posty)",
"text": "Tekst",
"theme": "Motyw",
"theme_help": "Użyj kolorów w notacji szesnastkowej (#rrggbb), by stworzyć swój motyw.",
"theme_help_v2_1": "Możesz też zastąpić kolory i widoczność poszczególnych komponentów przełączając pola wyboru, użyj „Wyczyść wszystko” aby usunąć wszystkie zastąpienia.",
"theme_help_v2_2": "Ikony pod niektórych wpisami są wskaźnikami kontrastu pomiędzy tłem a tekstem, po najechaniu na nie otrzymasz szczegółowe informacje. Zapamiętaj, że jeżeli używasz przezroczystości, wskaźniki pokazują najgorszy możliwy przypadek.",
"tooltipRadius": "Etykiety/alerty",
+ "type_domains_to_mute": "Wpisz domeny, które chcesz wyciszyć",
"upload_a_photo": "Wyślij zdjęcie",
"user_settings": "Ustawienia użytkownika",
"values": {
"false": "nie",
"true": "tak"
},
+ "fun": "Zabawa",
+ "greentext": "Memiczne strzałki",
"notifications": "Powiadomienia",
+ "notification_setting": "Otrzymuj powiadomienia od:",
+ "notification_setting_follows": "Ludzi których obserwujesz",
+ "notification_setting_non_follows": "Ludzi których nie obserwujesz",
+ "notification_setting_followers": "Ludzi którzy obserwują ciebie",
+ "notification_setting_non_followers": "Ludzi którzy nie obserwują ciebie",
+ "notification_mutes": "By przestać otrzymywać powiadomienia od jednego użytkownika, wycisz go",
+ "notification_blocks": "Blokowanie uzytkownika zatrzymuje wszystkie powiadomienia i odsubskrybowuje go.",
"enable_web_push_notifications": "Włącz powiadomienia push",
"style": {
"switcher": {
@@ -252,7 +422,24 @@
"save_load_hint": "Opcje „zachowaj” pozwalają na pozostanie przy obecnych opcjach po wybraniu lub załadowaniu motywu, jak i przechowywanie ich podczas eksportowania motywu. Jeżeli wszystkie są odznaczone, eksportowanie motywu spowoduje zapisanie wszystkiego.",
"reset": "Wyzeruj",
"clear_all": "Wyczyść wszystko",
- "clear_opacity": "Wyczyść widoczność"
+ "clear_opacity": "Wyczyść widoczność",
+ "load_theme": "Załaduj motyw",
+ "keep_as_is": "Zostaw po staremu",
+ "use_snapshot": "Stara wersja",
+ "use_source": "Nowa wersja",
+ "help": {
+ "upgraded_from_v2": "PleromaFE zostało zaaktualizowane, motyw może wyglądać nieco inaczej niż sobie zapamiętałeś.",
+ "v2_imported": "Plik który zaimportowałeś został stworzony dla starszego FE. Próbujemy zwiększyć kompatybiliność, lecz wciąż mogą występować rozbieżności.",
+ "future_version_imported": "Plik który zaimportowałeś został stworzony w nowszej wersji FE.",
+ "older_version_imported": "Plik który zaimportowałeś został stworzony w starszej wersji FE.",
+ "snapshot_present": "Migawka motywu jest załadowana, więc wszystkie wartości zostały nadpisane. Zamiast tego, możesz załadować właściwe dane motywu",
+ "snapshot_missing": "Nie znaleziono migawki motywu w pliku, więc motyw może wyglądać inaczej niż pierwotnie zaplanowano.",
+ "fe_upgraded": "Silnik motywów PleromaFE został zaaktualizowany.",
+ "fe_downgraded": "Wersja PleromaFE została cofnięta.",
+ "migration_snapshot_ok": "Żeby być bezpiecznym, migawka motywu została załadowana. Możesz spróbować załadować dane motywu.",
+ "migration_napshot_gone": "Z jakiegoś powodu migawka zniknęła, niektóre rzeczy mogą wyglądać inaczej niż sobie zapamiętałeś.",
+ "snapshot_source_mismatch": "Konflikt wersji: najprawdopodobniej FE zostało cofnięte do poprzedniej wersji i zaaktualizowane ponownie, jeśli zmieniłeś motyw używając starszej wersji FE, najprawdopodobniej chcesz używać starszej wersji, w przeciwnym razie użyj nowej wersji."
+ }
},
"common": {
"color": "Kolor",
@@ -280,14 +467,28 @@
"_tab_label": "Zaawansowane",
"alert": "Tło alertu",
"alert_error": "Błąd",
+ "alert_warning": "Ostrzeżenie",
+ "alert_neutral": "Neutralne",
+ "post": "Posty/Bio użytkowników",
"badge": "Tło odznaki",
+ "popover": "Etykiety, menu, popovery",
"badge_notification": "Powiadomienie",
"panel_header": "Nagłówek panelu",
"top_bar": "Górny pasek",
"borders": "Granice",
"buttons": "Przyciski",
"inputs": "Pola wejścia",
- "faint_text": "Zanikający tekst"
+ "faint_text": "Zanikający tekst",
+ "underlay": "Podkład",
+ "poll": "Wykres ankiety",
+ "icons": "Ikony",
+ "highlight": "Podświetlone elementy",
+ "pressed": "Naciśnięte",
+ "selectedPost": "Wybrany post",
+ "selectedMenu": "Wybrany element menu",
+ "disabled": "Wyłączone",
+ "toggled": "Przełączone",
+ "tabs": "Karty"
},
"radii": {
"_tab_label": "Zaokrąglenie"
@@ -300,7 +501,7 @@
"blur": "Rozmycie",
"spread": "Szerokość",
"inset": "Inset",
- "hint": "Możesz też używać --zmiennych jako kolorów, aby wykorzystać zmienne CSS3. Pamiętaj, że ustawienie widoczności nie będzie wtedy działać.",
+ "hintV3": "Dla cieni możesz również użyć notacji {0} by użyć inny slot koloru.",
"filter_hint": {
"always_drop_shadow": "Ostrzeżenie, ten cień zawsze używa {0} jeżeli to obsługiwane przez przeglądarkę.",
"drop_shadow_syntax": "{0} nie obsługuje parametru {1} i słowa kluczowego {2}.",
@@ -357,6 +558,40 @@
"frontend_version": "Wersja front-endu"
}
},
+ "time": {
+ "day": "{0} dzień",
+ "days": "{0} dni",
+ "day_short": "{0}d",
+ "days_short": "{0}d",
+ "hour": "{0} godzina",
+ "hours": "{0} godzin",
+ "hour_short": "{0} godz.",
+ "hours_short": "{0} godz.",
+ "in_future": "za {0}",
+ "in_past": "{0} temu",
+ "minute": "{0} minuta",
+ "minutes": "{0} minut",
+ "minute_short": "{0}min",
+ "minutes_short": "{0}min",
+ "month": "{0} miesiąc",
+ "months": "{0} miesięcy",
+ "month_short": "{0} mies.",
+ "months_short": "{0} mies.",
+ "now": "teraz",
+ "now_short": "teraz",
+ "second": "{0} sekunda",
+ "seconds": "{0} sekund",
+ "second_short": "{0}s",
+ "seconds_short": "{0}s",
+ "week": "{0} tydzień",
+ "weeks": "{0} tygodni",
+ "week_short": "{0} tydz.",
+ "weeks_short": "{0} tyg.",
+ "year": "{0} rok",
+ "years": "{0} lata",
+ "year_short": "{0} r.",
+ "years_short": "{0} lata"
+ },
"timeline": {
"collapse": "Zwiń",
"conversation": "Rozmowa",
@@ -370,8 +605,17 @@
"no_statuses": "Brak statusów"
},
"status": {
+ "favorites": "Ulubione",
+ "repeats": "Powtórzenia",
+ "delete": "Usuń status",
+ "pin": "Przypnij na profilu",
+ "unpin": "Odepnij z profilu",
+ "pinned": "Przypnięte",
+ "delete_confirm": "Czy naprawdę chcesz usunąć ten status?",
"reply_to": "Odpowiedź dla",
- "replies_list": "Odpowiedzi:"
+ "replies_list": "Odpowiedzi:",
+ "mute_conversation": "Wycisz konwersację",
+ "unmute_conversation": "Odcisz konwersację"
},
"user_card": {
"approve": "Przyjmij",
@@ -388,25 +632,60 @@
"followers": "Obserwujący",
"following": "Obserwowany!",
"follows_you": "Obserwuje cię!",
+ "hidden": "Ukryte",
"its_you": "To ty!",
"media": "Media",
+ "mention": "Wspomnienie",
"mute": "Wycisz",
"muted": "Wyciszony(-a)",
"per_day": "dziennie",
"remote_follow": "Zdalna obserwacja",
+ "report": "Raportuj",
"statuses": "Statusy",
+ "subscribe": "Subskrybuj",
+ "unsubscribe": "Odsubskrybuj",
"unblock": "Odblokuj",
"unblock_progress": "Odblokowuję…",
"block_progress": "Blokuję…",
"unmute": "Cofnij wyciszenie",
"unmute_progress": "Cofam wyciszenie…",
- "mute_progress": "Wyciszam…"
+ "mute_progress": "Wyciszam…",
+ "hide_repeats": "Ukryj powtórzenia",
+ "show_repeats": "Pokaż powtórzenia",
+ "admin_menu": {
+ "moderation": "Moderacja",
+ "grant_admin": "Przyznaj admina",
+ "revoke_admin": "Odwołaj admina",
+ "grant_moderator": "Przyznaj moderatora",
+ "revoke_moderator": "Odwołaj moderatora",
+ "activate_account": "Aktywuj konto",
+ "deactivate_account": "Dezaktywuj konto",
+ "delete_account": "Usuń konto",
+ "force_nsfw": "Oznacz wszystkie posty jako NSFW",
+ "strip_media": "Usuń multimedia z postów",
+ "force_unlisted": "Wymuś posty na niepubliczne",
+ "sandbox": "Wymuś by posty były tylko dla obserwujących",
+ "disable_remote_subscription": "Zakaż obserwowania użytkownika ze zdalnych instancji",
+ "disable_any_subscription": "Zakaż całkowicie obserwowania użytkownika",
+ "quarantine": "Zakaż federowania postów od tego użytkownika",
+ "delete_user": "Usuń użytkownika",
+ "delete_user_confirmation": "Czy jesteś absolutnie pewny? Ta operacja nie może być cofnięta."
+ }
},
"user_profile": {
"timeline_title": "Oś czasu użytkownika",
"profile_does_not_exist": "Przepraszamy, ten profil nie istnieje.",
"profile_loading_error": "Przepraszamy, wystąpił błąd podczas ładowania tego profilu."
},
+ "user_reporting": {
+ "title": "Raportowanie {0}",
+ "add_comment_description": "Raport zostanie wysłany do moderatorów instancji. Możesz dodać powód dlaczego raportujesz to konto poniżej:",
+ "additional_comments": "Dodatkowe komentarze",
+ "forward_description": "To konto jest z innego serwera. Wysłać również tam kopię raportu?",
+ "forward_to": "Przekaż do{0}",
+ "submit": "Wyślij",
+ "generic_error": "Wystąpił błąd podczas przetwarzania twojej prośby."
+ },
"who_to_follow": {
"more": "Więcej",
"who_to_follow": "Propozycje obserwacji"
@@ -416,6 +695,7 @@
"repeat": "Powtórz",
"reply": "Odpowiedz",
"favorite": "Dodaj do ulubionych",
+ "add_reaction": "Dodaj reakcję",
"user_settings": "Ustawienia użytkownika"
},
"upload":{
@@ -431,5 +711,25 @@
"GiB": "GiB",
"TiB": "TiB"
}
+ },
+ "search": {
+ "people": "Ludzie",
+ "hashtags": "Hasztagi",
+ "person_talking": "{count} osoba rozmawia o tym",
+ "people_talking": "{count} osób rozmawia o tym",
+ "no_results": "Brak wyników"
+ },
+ "password_reset": {
+ "forgot_password": "Zapomniałeś hasła?",
+ "password_reset": "Reset hasła",
+ "instruction": "Wprowadź swój adres email lub nazwę użytkownika. Wyślemy ci link z którym możesz zresetować hasło.",
+ "placeholder": "Twój email lub nazwa użytkownika",
+ "check_email": "Sprawdź pocztę, aby uzyskać link do zresetowania hasła.",
+ "return_home": "Wróć do strony głównej",
+ "not_found": "Nie mogliśmy znaleźć tego emaila lub nazwy użytkownika.",
+ "too_many_requests": "Przekroczyłeś limit prób, spróbuj ponownie później.",
+ "password_reset_disabled": "Resetowanie hasła jest wyłączone. Proszę skontaktuj się z administratorem tej instancji.",
+ "password_reset_required": "Musisz zresetować hasło, by się zalogować.",
+ "password_reset_required_but_mailer_is_disabled": "Musisz zresetować hasło, ale resetowanie hasła jest wyłączone. Proszę skontaktuj się z administratorem tej instancji."
}
}
diff --git a/src/main.js b/src/main.js
index baf73ac8..be4213fa 100644
--- a/src/main.js
+++ b/src/main.js
@@ -31,7 +31,6 @@ import VueChatScroll from 'vue-chat-scroll'
import VueClickOutside from 'v-click-outside'
import PortalVue from 'portal-vue'
import VBodyScrollLock from './directives/body_scroll_lock'
-import VTooltip from 'v-tooltip'
import afterStoreSetup from './boot/after_store.js'
@@ -44,13 +43,6 @@ Vue.use(VueChatScroll)
Vue.use(VueClickOutside)
Vue.use(PortalVue)
Vue.use(VBodyScrollLock)
-Vue.use(VTooltip, {
- popover: {
- defaultTrigger: 'hover click',
- defaultContainer: false,
- defaultOffset: 5
- }
-})
const i18n = new VueI18n({
// By default, use the browser locale, we will update it if neccessary
diff --git a/src/modules/config.js b/src/modules/config.js
index e6b373b4..7997521d 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -102,6 +102,7 @@ const config = {
setPreset(value)
break
case 'customTheme':
+ case 'customThemeSource':
applyTheme(value)
}
}
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 8781646d..ffece311 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -1,5 +1,6 @@
import { set } from 'vue'
import { getPreset, applyTheme } from '../services/style_setter/style_setter.js'
+import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
import { instanceDefaultProperties } from './config.js'
const defaultState = {
@@ -159,7 +160,14 @@ const instance = {
// No need to apply theme if there's user theme already
const { customTheme } = rootState.config
if (customTheme) return
- applyTheme(themeData.theme)
+
+ // New theme presets don't have 'theme' property, they use 'source'
+ const themeSource = themeData.source
+ if (!themeData.theme || (themeSource && themeSource.themeEngineVersion === CURRENT_VERSION)) {
+ applyTheme(themeSource)
+ } else {
+ applyTheme(themeData.theme)
+ }
})
},
fetchEmoji ({ dispatch, state }) {
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 25b62ac7..f1b7dcbd 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -616,7 +616,7 @@ const statuses = {
commit('setNotificationsSilence', { value })
},
fetchStatus ({ rootState, dispatch }, id) {
- rootState.api.backendInteractor.fetchStatus({ id })
+ return rootState.api.backendInteractor.fetchStatus({ id })
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
},
deleteStatus ({ rootState, commit }, status) {
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 03e88ae2..ad2b2ad5 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -540,7 +540,7 @@ const fetchTimeline = ({
params.push(['with_move', withMove])
}
- params.push(['count', 20])
+ params.push(['limit', 20])
params.push(['with_muted', withMuted])
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
@@ -880,12 +880,20 @@ const fetchPoll = ({ pollId, credentials }) => {
)
}
-const fetchFavoritedByUsers = ({ id }) => {
- return promisedRequest({ url: MASTODON_STATUS_FAVORITEDBY_URL(id) }).then((users) => users.map(parseUser))
+const fetchFavoritedByUsers = ({ id, credentials }) => {
+ return promisedRequest({
+ url: MASTODON_STATUS_FAVORITEDBY_URL(id),
+ method: 'GET',
+ credentials
+ }).then((users) => users.map(parseUser))
}
-const fetchRebloggedByUsers = ({ id }) => {
- return promisedRequest({ url: MASTODON_STATUS_REBLOGGEDBY_URL(id) }).then((users) => users.map(parseUser))
+const fetchRebloggedByUsers = ({ id, credentials }) => {
+ return promisedRequest({
+ url: MASTODON_STATUS_REBLOGGEDBY_URL(id),
+ method: 'GET',
+ credentials
+ }).then((users) => users.map(parseUser))
}
const fetchEmojiReactions = ({ id, credentials }) => {
diff --git a/src/services/theme_data/theme_data.service.js b/src/services/theme_data/theme_data.service.js
index e6ff82e6..dd87e3cf 100644
--- a/src/services/theme_data/theme_data.service.js
+++ b/src/services/theme_data/theme_data.service.js
@@ -350,16 +350,47 @@ export const getColors = (sourceColors, sourceOpacity) => SLOT_ORDERED.reduce(({
if (!outputColor) {
throw new Error('Couldn\'t generate color for ' + key)
}
- const opacitySlot = getOpacitySlot(key)
+
+ const opacitySlot = value.opacity || getOpacitySlot(key)
const ownOpacitySlot = value.opacity
- if (opacitySlot && (outputColor.a === undefined || ownOpacitySlot)) {
+
+ if (ownOpacitySlot === null) {
+ outputColor.a = 1
+ } else if (sourceColor === 'transparent') {
+ outputColor.a = 0
+ } else {
+ const opacityOverriden = ownOpacitySlot && sourceOpacity[opacitySlot] !== undefined
+
const dependencySlot = deps[0]
- if (dependencySlot && colors[dependencySlot] === 'transparent') {
- outputColor.a = 0
+ const dependencyColor = dependencySlot && colors[dependencySlot]
+
+ if (!ownOpacitySlot && dependencyColor && !value.textColor && ownOpacitySlot !== null) {
+ // Inheriting color from dependency (weird, i know)
+ // except if it's a text color or opacity slot is set to 'null'
+ outputColor.a = dependencyColor.a
+ } else if (!dependencyColor && !opacitySlot) {
+ // Remove any alpha channel if no dependency and no opacitySlot found
+ delete outputColor.a
} else {
- outputColor.a = Number(sourceOpacity[opacitySlot]) || OPACITIES[opacitySlot].defaultValue || 1
+ // Otherwise try to assign opacity
+ if (dependencyColor && dependencyColor.a === 0) {
+ // transparent dependency shall make dependents transparent too
+ outputColor.a = 0
+ } else {
+ // Otherwise check if opacity is overriden and use that or default value instead
+ outputColor.a = Number(
+ opacityOverriden
+ ? sourceOpacity[opacitySlot]
+ : (OPACITIES[opacitySlot] || {}).defaultValue
+ )
+ }
}
}
+
+ if (Number.isNaN(outputColor.a) || outputColor.a === undefined) {
+ outputColor.a = 1
+ }
+
if (opacitySlot) {
return {
colors: { ...colors, [key]: outputColor },
diff --git a/static/styles.json b/static/styles.json
index 3349a837..23f57c65 100644
--- a/static/styles.json
+++ b/static/styles.json
@@ -1,6 +1,6 @@
{
- "pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
- "pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
+ "pleroma-dark": "/static/themes/pleroma-dark.json",
+ "pleroma-light": "/static/themes/pleroma-light.json",
"pleroma-amoled": [ "Pleroma Dark AMOLED", "#000000", "#111111", "#b0b0b1", "#d8a070", "#aa0000", "#0fa00f", "#0095ff", "#d59500"],
"classic-dark": [ "Classic Dark", "#161c20", "#282e32", "#b9b9b9", "#baaa9c", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
"bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"],
diff --git a/static/themes/pleroma-dark.json b/static/themes/pleroma-dark.json
new file mode 100644
index 00000000..2703fba1
--- /dev/null
+++ b/static/themes/pleroma-dark.json
@@ -0,0 +1,191 @@
+{
+ "_pleroma_theme_version": 2,
+ "name": "Pleroma Dark",
+ "source": {
+ "themeEngineVersion": 3,
+ "fonts": {},
+ "shadows": {
+ "buttonHover": [
+ {
+ "x": 0,
+ "y": 0,
+ "blur": "1",
+ "spread": "2",
+ "color": "#b9b9ba",
+ "alpha": "0.4",
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": 1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#FFFFFF",
+ "alpha": 0.2,
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": -1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 0.2,
+ "inset": true
+ }
+ ],
+ "buttonPressed": [
+ {
+ "x": 0,
+ "y": 0,
+ "blur": 4,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 1,
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": 1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 0.2,
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": -1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#FFFFFF",
+ "alpha": 0.2,
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "blur": "2",
+ "spread": 0,
+ "inset": false,
+ "color": "#000000",
+ "alpha": 1
+ }
+ ],
+ "panelHeader": [
+ {
+ "x": 0,
+ "y": "1",
+ "blur": "3",
+ "spread": 0,
+ "inset": false,
+ "color": "#000000",
+ "alpha": "0.4"
+ },
+ {
+ "x": "0",
+ "y": "1",
+ "blur": "0",
+ "spread": 0,
+ "inset": true,
+ "color": "#ffffff",
+ "alpha": "0.2"
+ }
+ ],
+ "panel": [
+ {
+ "x": "0",
+ "y": "0",
+ "blur": "3",
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.5"
+ },
+ {
+ "x": "0",
+ "y": "4",
+ "blur": "6",
+ "spread": "3",
+ "inset": false,
+ "color": "#000000",
+ "alpha": "0.3"
+ }
+ ],
+ "button": [
+ {
+ "x": 0,
+ "y": 0,
+ "blur": 2,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 1
+ },
+ {
+ "x": 0,
+ "y": 1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#FFFFFF",
+ "alpha": 0.2,
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": -1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 0.2,
+ "inset": true
+ }
+ ],
+ "topBar": [
+ {
+ "x": 0,
+ "y": "1",
+ "blur": 4,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.4"
+ },
+ {
+ "x": 0,
+ "y": "2",
+ "blur": "7",
+ "spread": 0,
+ "inset": false,
+ "color": "#000000",
+ "alpha": "0.3"
+ }
+ ]
+ },
+ "opacity": {
+ "underlay": "0.6"
+ },
+ "colors": {
+ "bg": "#0f161e",
+ "fg": "#151e2b",
+ "text": "#b9b9ba",
+ "underlay": "#090e14",
+ "accent": "#e2b188",
+ "cBlue": "#81beea",
+ "cRed": "#d31014",
+ "cGreen": "#5dc94a",
+ "cOrange": "#ffc459",
+ "border": "--fg,3",
+ "topBarText": "--text,-9.75",
+ "topBarLink": "--topBarText",
+ "btnToggled": "--accent,-24.2",
+ "alertErrorText": "--text,21.2",
+ "badgeNotification": "#e15932",
+ "badgeNotificationText": "#ffffff"
+ },
+ "radii": {
+ "btn": "3",
+ "input": "3",
+ "panel": "3",
+ "avatar": "3",
+ "attachment": "3"
+ }
+ }
+}
diff --git a/static/themes/pleroma-light.json b/static/themes/pleroma-light.json
new file mode 100644
index 00000000..05fc300a
--- /dev/null
+++ b/static/themes/pleroma-light.json
@@ -0,0 +1,219 @@
+{
+ "_pleroma_theme_version": 2,
+ "name": "Pleroma Light",
+ "source": {
+ "themeEngineVersion": 3,
+ "fonts": {},
+ "shadows": {
+ "button": [
+ {
+ "x": 0,
+ "y": 0,
+ "blur": 2,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.2"
+ },
+ {
+ "x": 0,
+ "y": 1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#FFFFFF",
+ "alpha": "0.5",
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": -1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 0.2,
+ "inset": true
+ }
+ ],
+ "buttonHover": [
+ {
+ "x": 0,
+ "y": 0,
+ "blur": "2",
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.2"
+ },
+ {
+ "x": 0,
+ "y": "0",
+ "blur": "1",
+ "spread": "2",
+ "color": "#ffc39f",
+ "alpha": "1",
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": -1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 0.2,
+ "inset": true
+ }
+ ],
+ "input": [
+ {
+ "x": 0,
+ "y": 1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": 0.2,
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": -1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#FFFFFF",
+ "alpha": 0.2,
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "blur": "2",
+ "inset": true,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.15"
+ }
+ ],
+ "panel": [
+ {
+ "x": "0",
+ "y": 1,
+ "blur": "3",
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.5"
+ },
+ {
+ "x": "0",
+ "y": "3",
+ "blur": "6",
+ "spread": "1",
+ "inset": false,
+ "color": "#000000",
+ "alpha": "0.2"
+ }
+ ],
+ "panelHeader": [
+ {
+ "x": 0,
+ "y": "1",
+ "blur": 0,
+ "spread": 0,
+ "inset": true,
+ "color": "#ffffff",
+ "alpha": "0.5"
+ },
+ {
+ "x": 0,
+ "y": "1",
+ "blur": "3",
+ "spread": 0,
+ "inset": false,
+ "color": "#000000",
+ "alpha": "0.3"
+ }
+ ],
+ "buttonPressed": [
+ {
+ "x": 0,
+ "y": 0,
+ "blur": 4,
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.2"
+ },
+ {
+ "x": 0,
+ "y": 1,
+ "blur": "1",
+ "spread": "2",
+ "color": "#000000",
+ "alpha": "0.3",
+ "inset": true
+ },
+ {
+ "x": 0,
+ "y": -1,
+ "blur": 0,
+ "spread": 0,
+ "color": "#FFFFFF",
+ "alpha": 0.2,
+ "inset": true
+ }
+ ],
+ "popup": [
+ {
+ "x": "1",
+ "y": "2",
+ "blur": "2",
+ "spread": 0,
+ "color": "#000000",
+ "alpha": "0.2"
+ },
+ {
+ "x": "1",
+ "y": "3",
+ "blur": "7",
+ "spread": "0",
+ "inset": false,
+ "color": "#000000",
+ "alpha": "0.2"
+ }
+ ],
+ "avatarStatus": [
+ {
+ "x": 0,
+ "y": "1",
+ "blur": "4",
+ "spread": "0",
+ "inset": false,
+ "color": "#000000",
+ "alpha": "0.2"
+ }
+ ]
+ },
+ "opacity": {
+ "underlay": "0.4"
+ },
+ "colors": {
+ "bg": "#f2f6f9",
+ "fg": "#d6dfed",
+ "text": "#304055",
+ "underlay": "#5d6086",
+ "accent": "#f55b1b",
+ "cBlue": "#0095ff",
+ "cRed": "#d31014",
+ "cGreen": "#0fa00f",
+ "cOrange": "#ffa500",
+ "border": "#d8e6f9",
+ "topBarText": "#304055",
+ "topBarLink": "--topBarText",
+ "btnToggled": "--accent,-24.2",
+ "input": "#dee3ed",
+ "badgeNotification": "#e83802"
+ },
+ "radii": {
+ "btn": "3",
+ "input": "3",
+ "panel": "3",
+ "avatar": "3",
+ "attachment": "3"
+ }
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index b794042f..0defefcb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5941,11 +5941,6 @@ pngjs@^3.3.0:
version "3.3.3"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b"
-popper.js@^1.15.0:
- version "1.15.0"
- resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2"
- integrity sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==
-
portal-vue@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-2.1.4.tgz#1fc679d77e294dc8d026f1eb84aa467de11b392e"
@@ -7823,15 +7818,6 @@ v-click-outside@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/v-click-outside/-/v-click-outside-2.1.3.tgz#b7297abe833a439dc0895e6418a494381e64b5e7"
-v-tooltip@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/v-tooltip/-/v-tooltip-2.0.2.tgz#8610d9eece2cc44fd66c12ef2f12eec6435cab9b"
- integrity sha512-xQ+qzOFfywkLdjHknRPgMMupQNS8yJtf9Utd5Dxiu/0n4HtrxqsgDtN2MLZ0LKbburtSAQgyypuE/snM8bBZhw==
- dependencies:
- lodash "^4.17.11"
- popper.js "^1.15.0"
- vue-resize "^0.4.5"
-
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
@@ -7906,11 +7892,6 @@ vue-loader@^14.0.0:
vue-style-loader "^4.0.1"
vue-template-es2015-compiler "^1.6.0"
-vue-resize@^0.4.5:
- version "0.4.5"
- resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-0.4.5.tgz#4777a23042e3c05620d9cbda01c0b3cc5e32dcea"
- integrity sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg==
-
vue-router@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"