aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/announcement/announcement.js3
-rw-r--r--src/components/announcement/announcement.vue4
-rw-r--r--src/components/announcements_page/announcements_page.js3
-rw-r--r--src/components/announcements_page/announcements_page.vue2
-rw-r--r--src/components/emoji_picker/emoji_picker.js6
-rw-r--r--src/components/lists_edit/lists_edit.js4
-rw-r--r--src/components/navigation/filter.js2
-rw-r--r--src/components/navigation/navigation_pins.js10
-rw-r--r--src/components/notification/notification.js14
-rw-r--r--src/components/notification/notification.vue20
-rw-r--r--src/components/notifications/notifications.js3
-rw-r--r--src/components/notifications/notifications.scss10
-rw-r--r--src/components/registration/registration.vue4
-rw-r--r--src/components/settings_modal/helpers/boolean_setting.js6
-rw-r--r--src/components/settings_modal/tabs/data_import_export_tab.vue10
-rw-r--r--src/components/settings_modal/tabs/filtering_tab.js9
-rw-r--r--src/components/settings_modal/tabs/theme_tab/theme_tab.js4
-rw-r--r--src/components/timeline_menu/timeline_menu.js21
-rw-r--r--src/components/user_card/user_card.js13
-rw-r--r--src/components/user_card/user_card.scss4
-rw-r--r--src/components/user_card/user_card.vue6
-rw-r--r--src/components/user_note/user_note.js45
-rw-r--r--src/components/user_note/user_note.vue88
-rw-r--r--src/components/user_profile/user_profile.vue1
-rw-r--r--src/i18n/en.json14
-rw-r--r--src/i18n/eo.json78
-rw-r--r--src/i18n/uk.json112
-rw-r--r--src/modules/announcements.js2
-rw-r--r--src/modules/instance.js36
-rw-r--r--src/modules/users.js8
-rw-r--r--src/services/api/api.service.js15
31 files changed, 469 insertions, 88 deletions
diff --git a/src/components/announcement/announcement.js b/src/components/announcement/announcement.js
index c10c7d90..30254926 100644
--- a/src/components/announcement/announcement.js
+++ b/src/components/announcement/announcement.js
@@ -27,6 +27,9 @@ const Announcement = {
...mapState({
currentUser: state => state.users.currentUser
}),
+ canEditAnnouncement () {
+ return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
+ },
content () {
return this.announcement.content
},
diff --git a/src/components/announcement/announcement.vue b/src/components/announcement/announcement.vue
index 5f64232a..c1b35981 100644
--- a/src/components/announcement/announcement.vue
+++ b/src/components/announcement/announcement.vue
@@ -45,14 +45,14 @@
{{ $t('announcements.mark_as_read_action') }}
</button>
<button
- v-if="currentUser && currentUser.role === 'admin'"
+ v-if="canEditAnnouncement"
class="btn button-default"
@click="enterEditMode"
>
{{ $t('announcements.edit_action') }}
</button>
<button
- v-if="currentUser && currentUser.role === 'admin'"
+ v-if="canEditAnnouncement"
class="btn button-default"
@click="deleteAnnouncement"
>
diff --git a/src/components/announcements_page/announcements_page.js b/src/components/announcements_page/announcements_page.js
index 0bb4892e..8d1204d4 100644
--- a/src/components/announcements_page/announcements_page.js
+++ b/src/components/announcements_page/announcements_page.js
@@ -28,6 +28,9 @@ const AnnouncementsPage = {
}),
announcements () {
return this.$store.state.announcements.announcements
+ },
+ canPostAnnouncement () {
+ return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
}
},
methods: {
diff --git a/src/components/announcements_page/announcements_page.vue b/src/components/announcements_page/announcements_page.vue
index b1489dec..59ed283d 100644
--- a/src/components/announcements_page/announcements_page.vue
+++ b/src/components/announcements_page/announcements_page.vue
@@ -7,7 +7,7 @@
</div>
<div class="panel-body">
<section
- v-if="currentUser && currentUser.role === 'admin'"
+ v-if="canPostAnnouncement"
>
<div class="post-form">
<div class="heading">
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index dd5e5217..2838e102 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -287,7 +287,11 @@ const EmojiPicker = {
return 0
},
allCustomGroups () {
- return this.$store.getters.groupedCustomEmojis
+ const emojis = this.$store.getters.groupedCustomEmojis
+ if (emojis.unpacked) {
+ emojis.unpacked.text = this.$t('emoji.unpacked')
+ }
+ return emojis
},
defaultGroup () {
return Object.keys(this.allCustomGroups)[0]
diff --git a/src/components/lists_edit/lists_edit.js b/src/components/lists_edit/lists_edit.js
index c22d1323..c33659df 100644
--- a/src/components/lists_edit/lists_edit.js
+++ b/src/components/lists_edit/lists_edit.js
@@ -95,10 +95,10 @@ const ListsNew = {
return this.addedUserIds.has(user.id)
},
addUser (user) {
- this.$store.dispatch('addListAccount', { accountId: this.user.id, listId: this.id })
+ this.$store.dispatch('addListAccount', { accountId: user.id, listId: this.id })
},
removeUser (userId) {
- this.$store.dispatch('removeListAccount', { accountId: this.user.id, listId: this.id })
+ this.$store.dispatch('removeListAccount', { accountId: userId, listId: this.id })
},
onSearchLoading (results) {
this.searchLoading = true
diff --git a/src/components/navigation/filter.js b/src/components/navigation/filter.js
index 5474a8ac..e8e77f8f 100644
--- a/src/components/navigation/filter.js
+++ b/src/components/navigation/filter.js
@@ -2,7 +2,7 @@ export const filterNavigation = (list = [], { hasChats, hasAnnouncements, isFede
return list.filter(({ criteria, anon, anonRoute }) => {
const set = new Set(criteria || [])
if (!isFederating && set.has('federating')) return false
- if (isPrivate && set.has('!private')) return false
+ if (!currentUser && isPrivate && set.has('!private')) return false
if (!currentUser && !(anon || anonRoute)) return false
if ((!currentUser || !currentUser.locked) && set.has('lockedUser')) return false
if (!hasChats && set.has('chats')) return false
diff --git a/src/components/navigation/navigation_pins.js b/src/components/navigation/navigation_pins.js
index 57b8d589..9dd795aa 100644
--- a/src/components/navigation/navigation_pins.js
+++ b/src/components/navigation/navigation_pins.js
@@ -56,11 +56,17 @@ const NavPanel = {
}),
pinnedList () {
if (!this.currentUser) {
- return [
+ return filterNavigation([
{ ...TIMELINES.public, name: 'public' },
{ ...TIMELINES.twkn, name: 'twkn' },
{ ...ROOT_ITEMS.about, name: 'about' }
- ]
+ ],
+ {
+ hasChats: this.pleromaChatMessagesAvailable,
+ isFederating: this.federating,
+ isPrivate: this.privateMode,
+ currentUser: this.currentUser
+ })
}
return filterNavigation(
[
diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js
index ddba560e..265aaee0 100644
--- a/src/components/notification/notification.js
+++ b/src/components/notification/notification.js
@@ -20,7 +20,9 @@ import {
faUserPlus,
faEyeSlash,
faUser,
- faSuitcaseRolling
+ faSuitcaseRolling,
+ faExpandAlt,
+ faCompressAlt
} from '@fortawesome/free-solid-svg-icons'
library.add(
@@ -31,13 +33,15 @@ library.add(
faUserPlus,
faUser,
faEyeSlash,
- faSuitcaseRolling
+ faSuitcaseRolling,
+ faExpandAlt,
+ faCompressAlt
)
const Notification = {
data () {
return {
- userExpanded: false,
+ statusExpanded: false,
betterShadow: this.$store.state.interface.browserSupport.cssFilter,
unmuted: false
}
@@ -55,8 +59,8 @@ const Notification = {
UserLink
},
methods: {
- toggleUserExpanded () {
- this.userExpanded = !this.userExpanded
+ toggleStatusExpanded () {
+ this.statusExpanded = !this.statusExpanded
},
generateUserProfileLink (user) {
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 84f3f7de..f1aa5420 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -144,13 +144,25 @@
<router-link
v-if="notification.status"
:to="{ name: 'conversation', params: { id: notification.status.id } }"
- class="faint-link"
+ class="timeago-link faint-link"
>
<Timeago
:time="notification.created_at"
:auto-update="240"
/>
</router-link>
+ <button
+ class="button-unstyled expand-icon"
+ @click.prevent="toggleStatusExpanded"
+ :title="$t('tool_tip.toggle_expand')"
+ :aria-expanded="statusExpanded"
+ >
+ <FAIcon
+ class="fa-scale-110"
+ fixed-width
+ :icon="statusExpanded ? 'compress-alt' : 'expand-alt'"
+ />
+ </button>
</div>
<div
v-else
@@ -166,6 +178,8 @@
<button
v-if="needMute"
class="button-unstyled"
+ :title="$t('tool_tip.toggle_mute')"
+ :aria-expanded="!unmuted"
@click.prevent="toggleMute"
>
<FAIcon
@@ -222,8 +236,8 @@
/>
<template v-else>
<StatusContent
- class="faint"
- :compact="true"
+ :class="{ faint: !statusExpanded }"
+ :compact="!statusExpanded"
:status="notification.action"
/>
</template>
diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index dde9c93e..d499d3d6 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -101,6 +101,9 @@ const Notifications = {
if (!this.scrollerRef) {
this.scrollerRef = this.$refs.root.closest('.mobile-notifications')
}
+ if (!this.scrollerRef) {
+ this.scrollerRef = this.$refs.root.closest('.column.main')
+ }
this.scrollerRef.addEventListener('scroll', this.updateScrollPosition)
},
unmounted () {
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index f71f9b76..9b241565 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -112,6 +112,16 @@
min-width: 3em;
text-align: right;
}
+
+ .timeago-link {
+ margin-right: 0.2em;
+ }
+
+ .expand-icon {
+ .svg-inline--fa {
+ margin-left: 0.25em;
+ }
+ }
}
.emoji-reaction-emoji {
diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue
index d78d8da9..24d9b59b 100644
--- a/src/components/registration/registration.vue
+++ b/src/components/registration/registration.vue
@@ -158,10 +158,10 @@
class="form-error"
>
<ul>
- <li v-if="!v$.user.confirm.required">
+ <li v-if="v$.user.confirm.required.$invalid">
<span>{{ $t('registration.validations.password_confirmation_required') }}</span>
</li>
- <li v-if="!v$.user.confirm.sameAsPassword">
+ <li v-if="v$.user.confirm.sameAs.$invalid">
<span>{{ $t('registration.validations.password_confirmation_match') }}</span>
</li>
</ul>
diff --git a/src/components/settings_modal/helpers/boolean_setting.js b/src/components/settings_modal/helpers/boolean_setting.js
index dc832044..2e6992cb 100644
--- a/src/components/settings_modal/helpers/boolean_setting.js
+++ b/src/components/settings_modal/helpers/boolean_setting.js
@@ -41,7 +41,13 @@ export default {
},
methods: {
update (e) {
+ const [firstSegment, ...rest] = this.path.split('.')
set(this.$parent, this.path, e)
+ // Updating nested properties does not trigger update on its parent.
+ // probably still not as reliable, but works for depth=1 at least
+ if (rest.length > 0) {
+ set(this.$parent, firstSegment, { ...get(this.$parent, firstSegment) })
+ }
},
reset () {
set(this.$parent, this.path, this.defaultState)
diff --git a/src/components/settings_modal/tabs/data_import_export_tab.vue b/src/components/settings_modal/tabs/data_import_export_tab.vue
index e3b7f407..48356c9b 100644
--- a/src/components/settings_modal/tabs/data_import_export_tab.vue
+++ b/src/components/settings_modal/tabs/data_import_export_tab.vue
@@ -78,6 +78,16 @@
{{ $t('settings.download_backup') }}
</a>
<span
+ v-else-if="backup.state === 'running'"
+ >
+ {{ $tc('settings.backup_running', backup.processed_number, { number: backup.processed_number }) }}
+ </span>
+ <span
+ v-else-if="backup.state === 'failed'"
+ >
+ {{ $t('settings.backup_failed') }}
+ </span>
+ <span
v-else
>
{{ $t('settings.backup_not_ready') }}
diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js
index 73413b48..5354e5db 100644
--- a/src/components/settings_modal/tabs/filtering_tab.js
+++ b/src/components/settings_modal/tabs/filtering_tab.js
@@ -38,15 +38,6 @@ const FilteringTab = {
},
// Updating nested properties
watch: {
- notificationVisibility: {
- handler (value) {
- this.$store.dispatch('setOption', {
- name: 'notificationVisibility',
- value: this.$store.getters.mergedConfig.notificationVisibility
- })
- },
- deep: true
- },
replyVisibility () {
this.$store.dispatch('queueFlushAll')
}
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
index 282cb384..4a739f73 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
@@ -279,6 +279,9 @@ export default {
opacity
)
+ // Temporary patch for null-y value errors
+ if (layers.flat().some(v => v == null)) return acc
+
return {
...acc,
...textColors.reduce((acc, textColorKey) => {
@@ -300,6 +303,7 @@ export default {
return Object.entries(ratios).reduce((acc, [k, v]) => { acc[k] = hints(v); return acc }, {})
} catch (e) {
console.warn('Failure computing contrasts', e)
+ return {}
}
},
previewRules () {
diff --git a/src/components/timeline_menu/timeline_menu.js b/src/components/timeline_menu/timeline_menu.js
index d74fbf4e..5a2a86c2 100644
--- a/src/components/timeline_menu/timeline_menu.js
+++ b/src/components/timeline_menu/timeline_menu.js
@@ -1,8 +1,10 @@
import Popover from '../popover/popover.vue'
import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
+import { mapState } from 'vuex'
import { ListsMenuContent } from '../lists_menu/lists_menu_content.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { TIMELINES } from 'src/components/navigation/navigation.js'
+import { filterNavigation } from 'src/components/navigation/filter.js'
import {
faChevronDown
} from '@fortawesome/free-solid-svg-icons'
@@ -29,8 +31,7 @@ const TimelineMenu = {
},
data () {
return {
- isOpen: false,
- timelinesList: Object.entries(TIMELINES).map(([k, v]) => ({ ...v, name: k }))
+ isOpen: false
}
},
created () {
@@ -42,6 +43,22 @@ const TimelineMenu = {
useListsMenu () {
const route = this.$route.name
return route === 'lists-timeline'
+ },
+ ...mapState({
+ currentUser: state => state.users.currentUser,
+ privateMode: state => state.instance.private,
+ federating: state => state.instance.federating
+ }),
+ timelinesList () {
+ return filterNavigation(
+ Object.entries(TIMELINES).map(([k, v]) => ({ ...v, name: k })),
+ {
+ hasChats: this.pleromaChatMessagesAvailable,
+ isFederating: this.federating,
+ isPrivate: this.privateMode,
+ currentUser: this.currentUser
+ }
+ )
}
},
methods: {
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 8b64a07e..67879307 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -4,6 +4,7 @@ import ProgressButton from '../progress_button/progress_button.vue'
import FollowButton from '../follow_button/follow_button.vue'
import ModerationTools from '../moderation_tools/moderation_tools.vue'
import AccountActions from '../account_actions/account_actions.vue'
+import UserNote from '../user_note/user_note.vue'
import Select from '../select/select.vue'
import UserLink from '../user_link/user_link.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx'
@@ -39,7 +40,8 @@ export default {
'rounded',
'bordered',
'avatarAction', // default - open profile, 'zoom' - zoom, function - call function
- 'onClose'
+ 'onClose',
+ 'hasNoteEditor'
],
data () {
return {
@@ -129,6 +131,12 @@ export default {
const privileges = this.loggedIn.privileges
return this.loggedIn.role === 'admin' || privileges.includes('users_manage_activation_state') || privileges.includes('users_delete') || privileges.includes('users_manage_tags')
},
+ hasNote () {
+ return this.relationship.note
+ },
+ supportsNote () {
+ return 'note' in this.relationship
+ },
...mapGetters(['mergedConfig'])
},
components: {
@@ -140,7 +148,8 @@ export default {
FollowButton,
Select,
RichContent,
- UserLink
+ UserLink,
+ UserNote
},
methods: {
muteUser () {
diff --git a/src/components/user_card/user_card.scss b/src/components/user_card/user_card.scss
index a0bbc6a6..cdb8cb57 100644
--- a/src/components/user_card/user_card.scss
+++ b/src/components/user_card/user_card.scss
@@ -315,6 +315,10 @@
margin: 0;
}
}
+
+ .user-note {
+ margin: 0 .75em .6em 0;
+ }
}
.sidebar .edit-profile-button {
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 897d89f9..349c7cb1 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -268,6 +268,12 @@
>
<RemoteFollow :user="user" />
</div>
+ <UserNote
+ v-if="loggedIn && isOtherUser && (hasNote || (hasNoteEditor && supportsNote))"
+ :user="user"
+ :relationship="relationship"
+ :editable="hasNoteEditor"
+ />
</div>
</div>
<div
diff --git a/src/components/user_note/user_note.js b/src/components/user_note/user_note.js
new file mode 100644
index 00000000..830b2e59
--- /dev/null
+++ b/src/components/user_note/user_note.js
@@ -0,0 +1,45 @@
+const UserNote = {
+ props: {
+ user: Object,
+ relationship: Object,
+ editable: Boolean
+ },
+ data () {
+ return {
+ localNote: '',
+ editing: false,
+ frozen: false
+ }
+ },
+ computed: {
+ shouldShow () {
+ return this.relationship.note || this.editing
+ }
+ },
+ methods: {
+ startEditing () {
+ this.localNote = this.relationship.note
+ this.editing = true
+ },
+ cancelEditing () {
+ this.editing = false
+ },
+ finalizeEditing () {
+ this.frozen = true
+
+ this.$store.dispatch('editUserNote', {
+ id: this.user.id,
+ comment: this.localNote
+ })
+ .then(() => {
+ this.frozen = false
+ this.editing = false
+ })
+ .catch(() => {
+ this.frozen = false
+ })
+ }
+ }
+}
+
+export default UserNote
diff --git a/src/components/user_note/user_note.vue b/src/components/user_note/user_note.vue
new file mode 100644
index 00000000..4286e017
--- /dev/null
+++ b/src/components/user_note/user_note.vue
@@ -0,0 +1,88 @@
+<template>
+ <div
+ class="user-note"
+ >
+ <div class="heading">
+ <span>{{ $t('user_card.note') }}</span>
+ <div class="buttons">
+ <button
+ v-show="!editing && editable"
+ class="button-default btn"
+ @click="startEditing"
+ >
+ {{ $t('user_card.edit_note') }}
+ </button>
+ <button
+ v-show="editing"
+ class="button-default btn"
+ :disabled="frozen"
+ @click="finalizeEditing"
+ >
+ {{ $t('user_card.edit_note_apply') }}
+ </button>
+ <button
+ v-show="editing"
+ class="button-default btn"
+ :disabled="frozen"
+ @click="cancelEditing"
+ >
+ {{ $t('user_card.edit_note_cancel') }}
+ </button>
+ </div>
+ </div>
+ <textarea
+ v-show="editing"
+ v-model="localNote"
+ class="note-text"
+ />
+ <span
+ v-show="!editing"
+ class="note-text"
+ :class="{ '-blank': !relationship.note }"
+ >
+ {{ relationship.note || $t('user_card.note_blank') }}
+ </span>
+ </div>
+</template>
+
+<script src="./user_note.js"></script>
+
+<style lang="scss">
+@import '../../variables';
+
+.user-note {
+ display: flex;
+ flex-direction: column;
+
+ .heading {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 0.75em;
+
+ .btn {
+ min-width: 95px;
+ }
+
+ .buttons {
+ display: flex;
+ flex-direction: row;
+ justify-content: right;
+
+ .btn {
+ margin-left: 0.5em;
+ }
+ }
+ }
+
+ .note-text {
+ align-self: stretch;
+ }
+
+ .note-text.-blank {
+ font-style: italic;
+ color: var(--faint, $fallback--faint);
+ }
+}
+</style>
diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue
index d0da2b5b..d5e8d230 100644
--- a/src/components/user_profile/user_profile.vue
+++ b/src/components/user_profile/user_profile.vue
@@ -10,6 +10,7 @@
:selected="timeline.viewing"
avatar-action="zoom"
rounded="top"
+ :has-note-editor="true"
/>
<div
v-if="user.fields_html && user.fields_html.length > 0"
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 5793c3c8..1ee1147a 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -225,6 +225,7 @@
"search_emoji": "Search for an emoji",
"add_emoji": "Insert emoji",
"custom": "Custom emoji",
+ "unpacked": "Unpacked emoji",
"unicode": "Unicode emoji",
"unicode_groups": {
"activities": "Activities",
@@ -390,6 +391,8 @@
"account_backup_table_head": "Backup",
"download_backup": "Download",
"backup_not_ready": "This backup is not ready yet.",
+ "backup_running": "This backup is in progress, processed {number} record. | This backup is in progress, processed {number} records.",
+ "backup_failed": "This backup has failed.",
"remove_backup": "Remove",
"list_backups_error": "Error fetching backup list: {error}",
"add_backup": "Create a new backup",
@@ -957,7 +960,12 @@
"solid": "Solid bg",
"striped": "Striped bg",
"side": "Side stripe"
- }
+ },
+ "note": "Note",
+ "note_blank": "(None)",
+ "edit_note": "Edit note",
+ "edit_note_apply": "Apply",
+ "edit_note_cancel": "Cancel"
},
"user_profile": {
"timeline_title": "User timeline",
@@ -986,7 +994,9 @@
"user_settings": "User Settings",
"accept_follow_request": "Accept follow request",
"reject_follow_request": "Reject follow request",
- "bookmark": "Bookmark"
+ "bookmark": "Bookmark",
+ "toggle_expand": "Expand or collapse notification to show post in full",
+ "toggle_mute": "Expand or collapse notification to reveal muted content"
},
"upload": {
"error": {
diff --git a/src/i18n/eo.json b/src/i18n/eo.json
index 5a2c8afb..3596065c 100644
--- a/src/i18n/eo.json
+++ b/src/i18n/eo.json
@@ -96,7 +96,7 @@
"friend_requests": "Petoj pri abono",
"mentions": "Mencioj",
"dms": "Rektaj mesaĝoj",
- "public_tl": "Loka historio",
+ "public_tl": "Noda historio",
"timeline": "Historio",
"twkn": "Federa historio",
"user_search": "Serĉi uzantojn",
@@ -112,16 +112,19 @@
"edit_pinned": "Redakti fiksitajn erojn",
"lists": "Listoj",
"edit_nav_mobile": "Adapti navigan breton",
- "edit_finish": "Fini redakton"
+ "edit_finish": "Fini redakton",
+ "mobile_notifications": "Malfermi sciigojn (estas nelegitaj)",
+ "mobile_notifications_close": "Fermi sciigojn",
+ "announcements": "Anoncoj"
},
"notifications": {
- "broken_favorite": "Nekonata stato, serĉante ĝin…",
- "favorited_you": "ŝatis vian staton",
+ "broken_favorite": "Nekonata afiŝo, serĉante ĝin…",
+ "favorited_you": "ŝatis vian afiŝon",
"followed_you": "ekabonis vin",
"load_older": "Enlegi pli malnovajn sciigojn",
"notifications": "Sciigoj",
"read": "Legite!",
- "repeated_you": "ripetis vian staton",
+ "repeated_you": "ripetis vian afiŝon",
"no_more_notifications": "Neniuj pliaj sciigoj",
"reacted_with": "reagis per {0}",
"migrated_to": "migris al",
@@ -131,7 +134,7 @@
"poll_ended": "enketo finiĝis"
},
"post_status": {
- "new_status": "Afiŝi novan staton",
+ "new_status": "Afiŝi",
"account_not_locked_warning": "Via konto ne estas {0}. Iu ajn povas vin aboni por vidi eĉ viajn afiŝoj nur por abonantoj.",
"account_not_locked_warning_link": "ŝlosita",
"attachments_sensitive": "Marki kunsendaĵojn konsternaj",
@@ -152,12 +155,12 @@
"unlisted": "Nelistigita – ne afiŝi al publikaj historioj"
},
"scope_notice": {
- "unlisted": "Ĉi tiu afiŝo ne estos videbla en la Loka historio kaj la Federa historio",
+ "unlisted": "Ĉi tiu afiŝo ne estos videbla en la Noda kaj la Federa historioj",
"private": "Ĉi tiu afiŝo estos videbla nur al viaj abonantoj",
"public": "Ĉi tiu afiŝo estos videbla al ĉiuj"
},
"media_description_error": "Malsukcesis afiŝo de vidaŭdaĵoj; reprovu",
- "empty_status_error": "Ne povas afiŝi malplenan staton sen dosieroj",
+ "empty_status_error": "Ne povas fari malplenan afiŝon sen dosieroj",
"preview_empty": "Malplena",
"preview": "Antaŭrigardo",
"direct_warning_to_first_only": "Ĉi tiu afiŝo estas nur videbla al uzantoj menciitaj je la komenco de la mesaĝo.",
@@ -166,7 +169,7 @@
"post": "Afiŝo",
"edit_remote_warning": "Aliaj foraj nodoj eble ne subtenas redaktadon, kaj ne povos ricevi pli novan version de via afiŝo.",
"edit_unsupported_warning": "Pleroma ne subtenas redaktadon de mencioj aŭ enketoj.",
- "edit_status": "Stato de redakto"
+ "edit_status": "Redakti afiŝon"
},
"registration": {
"bio": "Priskribo",
@@ -228,7 +231,7 @@
"avatar_size_instruction": "La rekomendata minimuma grando de profilbildoj estas 150×150 bilderoj.",
"export_theme": "Konservi antaŭagordon",
"filtering": "Filtrado",
- "filtering_explanation": "Ĉiuj statoj kun tiuj ĉi vortoj silentiĝos; skribu po unu linie",
+ "filtering_explanation": "Ĉiuj afiŝoj kun tiuj ĉi vortoj silentiĝos; skribu po unu linie",
"follow_export": "Elporto de abonoj",
"follow_export_button": "Elporti viajn abonojn al CSV-dosiero",
"follow_export_processing": "Traktante; baldaŭ vi ricevos peton elŝuti la dosieron",
@@ -245,7 +248,7 @@
"use_one_click_nsfw": "Malfermi konsternajn kunsendaĵojn per nur unu klako",
"hide_post_stats": "Kaŝi statistikon de afiŝoj (ekz. nombron de ŝatoj)",
"hide_user_stats": "Kaŝi statistikon de uzantoj (ekz. nombron de abonantoj)",
- "hide_filtered_statuses": "Kaŝi filtritajn statojn",
+ "hide_filtered_statuses": "Kaŝi ĉiujn filtritajn afiŝojn",
"import_followers_from_a_csv_file": "Enporti abonojn el CSV-dosiero",
"import_theme": "Enlegi antaŭagordojn",
"inputRadius": "Enigaj kampoj",
@@ -278,7 +281,7 @@
"hide_followers_description": "Ne montri kiu min sekvas",
"show_admin_badge": "Montri la insignon de administranto en mia profilo",
"show_moderator_badge": "Montri la insignon de reguligisto en mia profilo",
- "nsfw_clickthrough": "Ŝalti traklakan kaŝadon de kunsendaĵoj kaj antaŭmontroj de ligiloj por konsternaj statoj",
+ "nsfw_clickthrough": "Ŝalti traklakan kaŝadon de kunsendaĵoj kaj antaŭmontroj de ligiloj por konsternaj afiŝoj",
"oauth_tokens": "Pecoj de OAuth",
"token": "Peco",
"refresh_token": "Aktualiga peco",
@@ -627,14 +630,14 @@
"word_filter_and_more": "Vortofiltrado kaj pli…",
"mute_bot_posts": "Silentigi afiŝojn de robotoj",
"hide_bot_indication": "Kaŝi markon de roboteco en afiŝoj",
- "hide_wordfiltered_statuses": "Kaŝi vorte filtritajn statojn",
+ "hide_wordfiltered_statuses": "Kaŝi vorte filtritajn afiŝojn",
"hide_muted_threads": "Kaŝi silentigitajn fadenojn",
"account_privacy": "Privateco",
"user_profiles": "Profiloj de uzantoj",
"hide_favorites_description": "Ne montri liston de miaj ŝatatoj (oni tamen sciiĝas)",
"conversation_display_tree": "Arba stilo",
"conversation_display_tree_quick": "Arba vido",
- "show_scrollbars": "Montri rulumajn bretojn de flankaj kolumnoj",
+ "show_scrollbars": "Montri rulumskalojn de flankaj kolumnoj",
"third_column_mode_none": "Neniam montri trian kolumnon",
"third_column_mode_notifications": "Kolumno de sciigoj",
"columns": "Kolumnoj",
@@ -644,9 +647,9 @@
"column_sizes_notifs": "Sciigoj",
"tree_advanced": "Permesi pli flekseblan navigadon en arba vido",
"conversation_display_linear": "Linia stilo",
- "conversation_other_replies_button": "Montri la butonon «aliaj respondoj»",
- "conversation_other_replies_button_below": "Sub statoj",
- "conversation_other_replies_button_inside": "En statoj",
+ "conversation_other_replies_button": "Montri la butonon pri «aliaj respondoj»",
+ "conversation_other_replies_button_below": "Sub afiŝoj",
+ "conversation_other_replies_button_inside": "En afiŝoj",
"max_depth_in_thread": "Maksimuma nombro de niveloj implicite montrataj en fadeno",
"auto_update": "Montri novajn afiŝojn memage",
"use_at_icon": "Montri simbolon {'@'} kiel bildon anstataŭ teksto",
@@ -662,19 +665,20 @@
"user_popover_avatar_action_open": "Malfermi la profilon",
"user_popover_avatar_overlay": "Aperigi ŝprucaĵon pri uzanto sur profilbildo",
"show_yous": "Montri la markon «(Vi)»",
- "user_popover_avatar_action_zoom": "Zomi la profilbildon"
+ "user_popover_avatar_action_zoom": "Zomi la profilbildon",
+ "third_column_mode": "Kun sufiĉo da spaco, montri trian kolumnon kun"
},
"timeline": {
"collapse": "Maletendi",
"conversation": "Interparolo",
"error_fetching": "Eraris ĝisdatigo",
- "load_older": "Montri pli malnovajn statojn",
+ "load_older": "Montri pli malnovajn afiŝojn",
"no_retweet_hint": "Afiŝo estas markita kiel rekta aŭ nur por abonantoj, kaj ne eblas ĝin ripeti",
"repeated": "ripetis",
"show_new": "Montri novajn",
"up_to_date": "Ĝisdata",
- "no_more_statuses": "Neniuj pliaj statoj",
- "no_statuses": "Neniuj statoj",
+ "no_more_statuses": "Neniuj pliaj afiŝoj",
+ "no_statuses": "Neniuj afiŝoj",
"reload": "Enlegi ree",
"error": "Eraris akirado de historio: {0}",
"socket_reconnected": "Realtempa konekto fariĝis",
@@ -700,7 +704,7 @@
"muted": "Silentigita",
"per_day": "tage",
"remote_follow": "Fore aboni",
- "statuses": "Statoj",
+ "statuses": "Afiŝoj",
"unblock": "Malbloki",
"unblock_progress": "Malblokante…",
"block_progress": "Blokante…",
@@ -744,7 +748,12 @@
"edit_profile": "Redakti profilon",
"deactivated": "Malaktiva",
"follow_cancel": "Nuligi peton",
- "remove_follower": "Forigi abonanton"
+ "remove_follower": "Forigi abonanton",
+ "note": "Noto",
+ "note_blank": "(Neniu)",
+ "edit_note_apply": "Apliki",
+ "edit_note_cancel": "Nuligi",
+ "edit_note": "Redakti noton"
},
"user_profile": {
"timeline_title": "Historio de uzanto",
@@ -764,7 +773,9 @@
"bookmark": "Legosigno",
"reject_follow_request": "Rifuzi abonpeton",
"accept_follow_request": "Akcepti abonpeton",
- "add_reaction": "Aldoni reagon"
+ "add_reaction": "Aldoni reagon",
+ "toggle_expand": "Etendi aŭ maletendi sciigon por montri plenan afiŝon",
+ "toggle_mute": "Etendi aŭ maletendi afiŝon por montri silentigitan enhavon"
},
"upload": {
"error": {
@@ -893,19 +904,19 @@
"show_full_subject": "Montri plenan temon",
"thread_muted_and_words": ", enhavas vortojn:",
"thread_muted": "Fadeno silentigita",
- "copy_link": "Kopii ligilon al stato",
- "status_unavailable": "Stato ne estas disponebla",
+ "copy_link": "Kopii ligilon al afiŝo",
+ "status_unavailable": "Afiŝo ne estas disponebla",
"unmute_conversation": "Malsilentigi interparolon",
"mute_conversation": "Silentigi interparolon",
"replies_list": "Respondoj:",
"reply_to": "Responde al",
- "delete_confirm": "Ĉu vi certe volas forigi ĉi tiun staton?",
+ "delete_confirm": "Ĉu vi certe volas forigi ĉi tiun afiŝon?",
"unbookmark": "Senlegosigni",
"bookmark": "Legosigni",
"pinned": "Fiksita",
"unpin": "Malfiksi de profilo",
"pin": "Fiksi al profilo",
- "delete": "Forigi staton",
+ "delete": "Forigi afiŝon",
"repeats": "Ripetoj",
"favorites": "Ŝatoj",
"status_deleted": "Ĉi tiu afiŝo foriĝis",
@@ -939,7 +950,8 @@
"ancestor_follow_with_icon": "{icon} {text}",
"show_all_conversation_with_icon": "{icon} {text}",
"show_only_conversation_under_this": "Montri nur respondojn al ĉi tiu afiŝo",
- "status_history": "Historio de afiŝo"
+ "status_history": "Historio de afiŝo",
+ "open_gallery": "Malfermi galerion"
},
"time": {
"years_short": "{0}j",
@@ -996,7 +1008,9 @@
"no_results": "Neniuj rezultoj",
"people_talking": "{count} personoj parolas",
"person_talking": "{count} persono parolas",
- "hashtags": "Kradvortoj"
+ "hashtags": "Kradvortoj",
+ "no_more_results": "Neniuj pliaj rezultoj",
+ "load_more": "Enlegi pliajn rezultojn"
},
"display_date": {
"today": "Hodiaŭ"
@@ -1047,9 +1061,9 @@
"report": {
"reporter": "Raportinto:",
"reported_user": "Raportito:",
- "reported_statuses": "Raportitaj statoj:",
+ "reported_statuses": "Raportitaj afiŝoj:",
"notes": "Notoj:",
- "state": "Stato:",
+ "state": "Afiŝo:",
"state_open": "Malfermita",
"state_closed": "Fermita",
"state_resolved": "Solvita"
diff --git a/src/i18n/uk.json b/src/i18n/uk.json
index c75ed197..99b49868 100644
--- a/src/i18n/uk.json
+++ b/src/i18n/uk.json
@@ -32,7 +32,13 @@
"private": "Лише читачі",
"public": "Публічне",
"unlisted": "Непублічне"
- }
+ },
+ "undo": "Відмінити",
+ "yes": "Так",
+ "no": "Ні",
+ "unpin": "Відкріпити",
+ "scroll_to_top": "Вгору",
+ "pin": "Прикріпити"
},
"finder": {
"error_fetching_user": "Користувача не знайдено",
@@ -48,7 +54,7 @@
"media_proxy": "Посередник медіа-даних",
"text_limit": "Ліміт символів",
"upload_limit": "Обмеження завантажень",
- "shout": "Оголошення"
+ "shout": "Гучномовець"
},
"exporter": {
"processing": "Опрацьовую, скоро ви зможете завантажити файл",
@@ -61,7 +67,7 @@
"mute": "Ігнорувати"
},
"shoutbox": {
- "title": "Оголошення"
+ "title": "Гучномовець"
},
"about": {
"staff": "Адміністрація",
@@ -81,7 +87,8 @@
"accept_desc": "Поточний інстанс приймає повідомлення тільки з перелічених інстансів:",
"simple_policies": "Правила поточного інстансу",
"reason": "Причина",
- "not_applicable": "н/в"
+ "not_applicable": "н/в",
+ "instance": "Інстанс"
},
"mrf_policies_desc": "Правила MRF розповсюджуються на даний інстанс. Наступні правила активні:",
"mrf_policies": "Активувати правила MRF (модуль переписування повідомлень)",
@@ -153,7 +160,8 @@
"favorited_you": "вподобав(-ла) ваш допис",
"broken_favorite": "Невідомий допис, шукаю його…",
"error": "Помилка при оновленні сповіщень: {0}",
- "poll_ended": "опитування закінчено"
+ "poll_ended": "опитування закінчено",
+ "submitted_report": "подав скаргу"
},
"nav": {
"chats": "Чати",
@@ -174,7 +182,13 @@
"back": "Назад",
"administration": "Адміністрування",
"home_timeline": "Домашня стрічка",
- "lists": "Списки"
+ "lists": "Списки",
+ "edit_pinned": "Редагувати прикріплене",
+ "edit_finish": "Завершити редагування",
+ "mobile_sidebar": "Ввімкнути бокову панель",
+ "mobile_notifications": "Відкрити сповіщення (є непрочитані)",
+ "mobile_notifications_close": "Закрити сповіщення",
+ "edit_nav_mobile": "Редагувати панель навігації"
},
"media_modal": {
"next": "Наступна",
@@ -221,7 +235,8 @@
"follows": "Нові підписки",
"favs_repeats": "Поширення та вподобайки",
"moves": "Міграції користувачів",
- "emoji_reactions": "Емоджі реакції"
+ "emoji_reactions": "Емоджі реакції",
+ "reports": "Скарги"
},
"errors": {
"storage_unavailable": "Pleroma не змогла отримати доступ до сховища браузеру. Ваша сесія та налаштування не будуть збережені, це може спричинити непередбачувані проблеми. Спробуйте увімкнути cookie."
@@ -235,7 +250,19 @@
"emoji": "Емодзі",
"load_all": "Всі {emojiAmount} эмодзі завантажуються",
"load_all_hint": "Завантажені перші {saneAmount} емодзі, завантаження всіх емодзі може призвести до проблем з продуктивністю.",
- "unicode": "Стандартні емодзі"
+ "unicode": "Стандартні емодзі",
+ "regional_indicator": "Регіональний індикатор {letter}",
+ "unicode_groups": {
+ "animals-and-nature": "Тварини і Рослини",
+ "flags": "Прапори",
+ "food-and-drink": "Їжа та Напої",
+ "objects": "Об'єкти",
+ "people-and-body": "Люди та Тіло",
+ "smileys-and-emotion": "Смайлики та Емотікони",
+ "activities": "Активності",
+ "symbols": "Символи",
+ "travel-and-places": "Подорожі та Місця"
+ }
},
"post_status": {
"content_type": {
@@ -269,7 +296,10 @@
"preview_empty": "Пустий",
"media_description_error": "Не вдалось оновити медіа, спробуйте ще раз",
"media_description": "Опис медіа",
- "post": "Опублікувати"
+ "post": "Опублікувати",
+ "edit_unsupported_warning": "Pleroma не підтримує редагування згадувань чи голосувань.",
+ "edit_status": "Редагувати допис",
+ "edit_remote_warning": "Інші віддалені інстанси можуть не підтримувати редагування та вони можуть не отримати актуальну версію допису."
},
"settings": {
"blocks_imported": "Блокування імпортовані! Їх обробка триватиме певний час.",
@@ -654,7 +684,7 @@
"backup_restore": "Резервне копіювання налаштувань"
},
"right_sidebar": "Показувати бокову панель справа",
- "hide_shoutbox": "Приховати оголошення інстансу",
+ "hide_shoutbox": "Приховати гучномовець",
"setting_server_side": "Цей параметр прив’язаний до вашого профілю та впливає на всі сеанси та клієнти",
"lists_navigation": "Показувати списки в навігації",
"account_backup": "Резервне копіювання облікового запису",
@@ -682,7 +712,30 @@
"move_account": "Перемістити обліковий запис",
"move_account_target": "Цільовий обліковий запис (напр. {example})",
"moved_account": "Обліковий запис переміщено.",
- "move_account_error": "Помилка під час переміщення облікового запису: {error}"
+ "move_account_error": "Помилка під час переміщення облікового запису: {error}",
+ "word_filter_and_more": "Фільтр слів та більше...",
+ "hide_bot_indication": "Сховати позначку бот у дописах",
+ "navbar_column_stretch": "Розтягнути панель навігації на ширину колонок",
+ "hide_wordfiltered_statuses": "Ховати фільтровані статуси",
+ "hide_muted_threads": "Ховати приглушені треди",
+ "posts": "Дописи",
+ "account_privacy": "Безпека",
+ "conversation_display": "Стиль відображення розмови",
+ "conversation_display_tree": "Деревоподібне",
+ "conversation_display_tree_quick": "Вигляд дерева",
+ "disable_sticky_headers": "Не закріплювати заголовок колонки зверху на сторінці",
+ "third_column_mode_none": "Не показувати третю колонку взагалі",
+ "third_column_mode_notifications": "Колонка сповіщень",
+ "columns": "Колонки",
+ "auto_update": "Автоматично показувати нові дописи",
+ "use_websockets": "Використовувати вебсокети (Оновлення в реальному часі)",
+ "use_at_icon": "Показувати {'@'} символ як іконку замість тексту",
+ "mute_bot_posts": "Приховати дописи ботів",
+ "always_show_post_button": "Завжди показувати плаваючу кнопку «Новий Допис»",
+ "hide_favorites_description": "Не показувати список моїх вподобань (люди все одно отримують сповіщення)",
+ "third_column_mode": "Коли достатньо місця, показувати третю колонку, що містить",
+ "user_popover_avatar_action_open": "Відкрити профіль",
+ "wordfilter": "Фільтр слів"
},
"selectable_list": {
"select_all": "Вибрати все"
@@ -781,7 +834,23 @@
"day": "{0} день",
"seconds_short": "{0}с",
"seconds": "{0} секунди",
- "in_future": "через {0}"
+ "in_future": "через {0}",
+ "unit": {
+ "months": "{0} місяць | {0} місяців",
+ "minutes": "{0} хвилина | {0} хвилин",
+ "hours_short": "{0}год",
+ "minutes_short": "{0}хв",
+ "months_short": "{0}міс",
+ "seconds": "{0} секунда | {0} секунд",
+ "seconds_short": "{0}с",
+ "weeks_short": "{0}тижд",
+ "years": "{0} рік | {0} років",
+ "years_short": "{0}р.",
+ "days": "{0} день | {0} днів",
+ "days_short": "{0}д",
+ "hours": "{0} година | {0} годин",
+ "weeks": "{0} тиждень | {0} тижнів"
+ }
},
"search": {
"no_results": "Немає результатів",
@@ -850,7 +919,9 @@
"disabled": "Не виділяти"
},
"bot": "Бот",
- "edit_profile": "Редагувати профіль"
+ "edit_profile": "Редагувати профіль",
+ "deactivated": "Деактивований",
+ "follow_cancel": "Скасувати запит"
},
"status": {
"copy_link": "Скопіювати посилання на допис",
@@ -877,7 +948,15 @@
"thread_muted": "Нитка заглушена",
"unmute_conversation": "Припинити глушити розмову",
"external_source": "Зовнішнє джерело",
- "expand": "Розгорнути"
+ "expand": "Розгорнути",
+ "edit": "Редагувати допис",
+ "edited_at": "(змінено: {time})",
+ "thread_follow_with_icon": "{icon} {text}",
+ "ancestor_follow_with_icon": "{icon} {text}",
+ "show_all_conversation_with_icon": "{icon} {text}",
+ "plus_more": "+{number} більше",
+ "thread_show_full_with_icon": "{icon} {text}",
+ "show_only_conversation_under_this": "Показати всі відповіді на цей допис"
},
"timeline": {
"no_more_statuses": "Більше немає дописів",
@@ -913,6 +992,9 @@
"state": "Статус:",
"state_open": "відкритий",
"state_closed": "закритий",
- "state_resolved": "вирішений"
+ "state_resolved": "вирішений",
+ "reported_statuses": "Дописи, на які подано скаргу:",
+ "reporter": "Позивач:",
+ "reported_user": "Відповідач:"
}
}
diff --git a/src/modules/announcements.js b/src/modules/announcements.js
index e4d2d2b0..4504263b 100644
--- a/src/modules/announcements.js
+++ b/src/modules/announcements.js
@@ -49,7 +49,7 @@ const announcements = {
}
const currentUser = store.rootState.users.currentUser
- const isAdmin = currentUser && currentUser.role === 'admin'
+ const isAdmin = currentUser && currentUser.privileges.includes('announcements_manage_announcements')
const getAnnouncements = async () => {
if (!isAdmin) {
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 3b15e62e..8e8d13d3 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -181,15 +181,28 @@ const instance = {
},
groupedCustomEmojis (state) {
const packsOf = emoji => {
- return emoji.tags
+ const packs = emoji.tags
.filter(k => k.startsWith('pack:'))
- .map(k => k.slice(5)) // remove 'pack:' prefix
+ .map(k => {
+ const packName = k.slice(5) // remove 'pack:' prefix
+ return {
+ id: `custom-${packName}`,
+ text: packName
+ }
+ })
+
+ if (!packs.length) {
+ return [{
+ id: 'unpacked'
+ }]
+ } else {
+ return packs
+ }
}
return state.customEmoji
.reduce((res, emoji) => {
- packsOf(emoji).forEach(packName => {
- const packId = `custom-${packName}`
+ packsOf(emoji).forEach(({ id: packId, text: packName }) => {
if (!res[packId]) {
res[packId] = ({
id: packId,
@@ -290,9 +303,22 @@ const instance = {
const lb = b.toLowerCase()
return la > lb ? 1 : (la < lb ? -1 : 0)
}
+ const noPackLast = (a, b) => {
+ const aNull = a === ''
+ const bNull = b === ''
+ if (aNull === bNull) {
+ return 0
+ } else if (aNull && !bNull) {
+ return 1
+ } else {
+ return -1
+ }
+ }
const byPackThenByName = (a, b) => {
const packOf = emoji => (emoji.tags.filter(k => k.startsWith('pack:'))[0] || '').slice(5)
- return caseInsensitiveStrCmp(packOf(a), packOf(b)) || caseInsensitiveStrCmp(a.displayText, b.displayText)
+ const packOfA = packOf(a)
+ const packOfB = packOf(b)
+ return noPackLast(packOfA, packOfB) || caseInsensitiveStrCmp(packOfA, packOfB) || caseInsensitiveStrCmp(a.displayText, b.displayText)
}
const emoji = Object.entries(values).map(([key, value]) => {
diff --git a/src/modules/users.js b/src/modules/users.js
index 10b4603f..053e44b6 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -56,6 +56,11 @@ const removeUserFromFollowers = (store, id) => {
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
}
+const editUserNote = (store, { id, comment }) => {
+ return store.rootState.api.backendInteractor.editUserNote({ id, comment })
+ .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+}
+
const muteUser = (store, id) => {
const predictedRelationship = store.state.relationships[id] || { id }
predictedRelationship.muting = true
@@ -335,6 +340,9 @@ const users = {
unblockUsers (store, ids = []) {
return Promise.all(ids.map(id => unblockUser(store, id)))
},
+ editUserNote (store, args) {
+ return editUserNote(store, args)
+ },
fetchMutes (store) {
return store.rootState.api.backendInteractor.fetchMutes()
.then((mutes) => {
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index df652ae1..00d1c020 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -70,6 +70,7 @@ const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
const MASTODON_REMOVE_USER_FROM_FOLLOWERS = id => `/api/v1/accounts/${id}/remove_from_followers`
const MASTODON_SUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/subscribe`
const MASTODON_UNSUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/unsubscribe`
+const MASTODON_USER_NOTE_URL = id => `/api/v1/accounts/${id}/note`
const MASTODON_BOOKMARK_STATUS_URL = id => `/api/v1/statuses/${id}/bookmark`
const MASTODON_UNBOOKMARK_STATUS_URL = id => `/api/v1/statuses/${id}/unbookmark`
const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
@@ -163,7 +164,7 @@ const updateNotificationSettings = ({ credentials, settings }) => {
form.append(key, value)
})
- return fetch(NOTIFICATION_SETTINGS_URL, {
+ return fetch(`${NOTIFICATION_SETTINGS_URL}?${new URLSearchParams(settings)}`, {
headers: authHeaders(credentials),
method: 'PUT',
body: form
@@ -321,6 +322,17 @@ const removeUserFromFollowers = ({ id, credentials }) => {
}).then((data) => data.json())
}
+const editUserNote = ({ id, credentials, comment }) => {
+ return promisedRequest({
+ url: MASTODON_USER_NOTE_URL(id),
+ credentials,
+ payload: {
+ comment
+ },
+ method: 'POST'
+ })
+}
+
const approveUser = ({ id, credentials }) => {
const url = MASTODON_APPROVE_USER_URL(id)
return fetch(url, {
@@ -1667,6 +1679,7 @@ const apiService = {
blockUser,
unblockUser,
removeUserFromFollowers,
+ editUserNote,
fetchUser,
fetchUserByName,
fetchUserRelationship,