Page MenuHomePhorge

No OneTemporary

Size
37 KB
Referenced Files
None
Subscribers
None
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7eea72722..f6e529787a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,316 +1,317 @@
# Changelog
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
### Fixed
- AdminFE button no longer scrolls page to top when clicked
- Pinned statuses no longer appear at bottom of user timeline (still appear as part of the timeline when fetched deep enough)
- Fixed many many bugs related to new mentions, including spacing and alignment issues
- Links in profile bios now properly open in new tabs
- Inline images now respect their intended width/height attributes
- Links with `&` in them work properly now
- Interaction list popovers now properly emojify names
- Completely hidden posts still had 1px border
- Attachments are ALWAYS in same order as user uploaded, no more "videos first"
- Attachment description is prefilled with backend-provided default when uploading
- Proper visual feedback that next image is loading when browsing
- UI no longer lags when switching between mobile and desktop mode
- Popovers no longer constrained by DOM hierarchy, shouldn't be cut off by anything
- "Always show mobile button" is working now
### Changed
- Using Vue 3 now
- (You)s are optional (opt-in) now, bolding your nickname is also optional (opt-out)
- User highlight background now also covers the `@`
- Reverted back to textual `@`, svg version is opt-in.
- Settings window has been thoroughly rearranged to make more sense and make navigation settings easier.
- Uploaded attachments are uniform with displayed attachments
- Flash is watchable in media-modal (takes up nearly full screen though due to sizing issues)
- Notifications about likes/repeats/emoji reacts are now minimized so they always take up same amount of space irrelevant to size of post.
- Slight width/spacing adjustments
- More sizing stuff is font-size dependent now
- Scrollbars are styled/colorized now
- Scrollbars are toggleable (for stuff that didn't have visible scrollbars before) (opt-in)
### Added
- 3 column mode: only enables when there's space for it (opt-out, customizable)
- Options to show domains in mentions
- Option to show user avatars in mention links (opt-in)
- Option to disable the tooltip for mentions
- Option to completely hide muted threads
- Ability to open videos in modal even if you disabled that feature, via an icon button
- New button on attachment that indicates that attachment has a description and shows a bar filled with description
- Attachments are truncated just like post contents
- Media modal now also displays description and counter position in gallery (i.e. 1/5)
- Ability to rearrange order of attachments when uploading
- Enabled users to zoom and pan images in media viewer with mouse and touch
- Timelines/panels and conversations have sticky headers now
- Added frontend ui for account migration
+- Implemented remote interaction with statuses
## [2.4.2] - 2022-01-09
### Added
- Added Apply and Reset buttons to the bottom of theme tab to minimize UI travel
- Implemented user option to always show floating New Post button (normally mobile-only)
- Display reasons for instance specific policies
- Added functionality to cancel follow request
### Fixed
- Fixed link to external profile not working on user profiles
- Fixed mobile shoutbox display
- Fixed favicon badge not working in Chrome
- Escape html more properly in subject/display name
## [2.4.0] - 2021-08-08
### Added
- Added a quick settings to timeline header for easier access
- Added option to mark posts as sensitive by default
- Added quick filters for notifications
- Implemented user option to change sidebar position to the right side
- Implemented user option to hide floating shout panel
- Implemented "edit profile" button if viewing own profile which opens profile settings
### Fixed
- Fixed follow request count showing in the wrong location in mobile view
## [2.3.0] - 2021-03-01
### Fixed
- Button to remove uploaded media in post status form is now properly placed and sized.
- Fixed shoutbox not working in mobile layout
- Fixed missing highlighted border in expanded conversations again
- Fixed some UI jumpiness when opening images particularly in chat view
- Fixed chat unread badge looking weird
- Fixed punycode names not working properly
- Fixed notifications crashing on an invalid notification
### Changed
- Display 'people voted' instead of 'votes' for multi-choice polls
- Changed the "Timelines" link in side panel to toggle show all timeline options inside the panel
- Renamed "Timeline" to "Home Timeline" to be more clear
- Optimized chat to not get horrible performance after keeping the same chat open for a long time
- When opening emoji picker or react picker, it automatically focuses the search field
- Language picker now uses native language names
### Added
- Added reason field for registration when approval is required
- Group staff members by role in the About page
## [2.2.3] - 2021-01-18
### Added
- Added Report button to status ellipsis menu for easier reporting
### Fixed
- Follows/Followers tabs on user profiles now display the content properly.
- Handle punycode in screen names
- Fixed local dev mode having non-functional websockets in some cases
- Show notices for websocket events (errors, abnormal closures, reconnections)
- Fix not being able to re-enable websocket until page refresh
- Fix annoying issue where timeline might have few posts when streaming is enabled
### Changed
- Don't filter own posts when they hit your wordfilter
## [2.2.2] - 2020-12-22
### Added
- Mouseover titles for emojis in reaction picker
- Support to input emoji into the search box in reaction picker
- Added some missing unicode emoji
- Added the upload limit to the Features panel in the About page
- Support for solid color wallpaper, instance doesn't have to define a wallpaper anymore
### Fixed
- Fixed the occasional bug where screen would scroll 1px when typing into a reply form
- Fixed timeline errors locking timelines
- Fixed missing highlighted border in expanded conversations
- Fixed custom emoji not working in profile field names
- Fixed pinned statuses not appearing in user profiles
- Fixed some elements not being keyboard navigation friendly
- Fixed error handling when updating various profile images
- Fixed your latest chat messages disappearing when closing chat view and opening it again during the same session
- Fixed custom emoji not showing in poll options before voting
- Fixed link color not applied to instance name in topbar
### Changed
- Errors when fetching are now shown with popup errors instead of "Error fetching updates" in panel headers
- Made reply/fav/repeat etc buttons easier to hit
- Adjusted timeline menu clickable area to match the visible button
- Moved external source link from status heading to the ellipsis menu
- Disabled horizontal textarea resize
- Wallpaper is now top-aligned, horizontally centered.
## [2.2.1] - 2020-11-11
### Fixed
- Fixed regression in react popup alignment and overflowing
## [2.2.0] - 2020-11-06
### Added
- New option to optimize timeline rendering to make the site more responsive (enabled by default)
- New instance option `logoLeft` to move logo to the left side in desktop nav bar
- Import/export a muted users
- Proper handling of deletes when using websocket streaming
- Added optimistic chat message sending, so you can start writing next message before the previous one has been sent
- Added a small red badge to the favicon when there's unread notifications
- Added the NSFW alert to link previews
### Fixed
- Fixed clicking NSFW hider through status popover
- Fixed chat-view back button being hard to click
- Fixed fresh chat notifications being cleared immediately while leaving the chat view and not having time to actually see the messages
- Fixed multiple regressions in CSS styles
- Fixed multiple issues with input fields when using CJK font as default
- Fixed search field in navbar infringing into logo in some cases
- Fixed not being able to load the chat history in vertical screens when the message list doesn't take the full height of the scrollable container on the first fetch.
### Changed
- Clicking immediately when timeline shifts is now blocked to prevent misclicks
- Icons changed from fontello (FontAwesome 4 + others) to FontAwesome 5 due to problems with fontello.
- Some icons changed for better accessibility (lock, globe)
- Logo is now clickable
- Changed default logo to SVG version
## [2.1.2] - 2020-09-17
### Fixed
- Fixed chats list not updating its order when new messages come in
- Fixed chat messages sometimes getting lost when you receive a message at the same time
## [2.1.1] - 2020-09-08
### Changed
- Polls will be hidden with status content if "Collapse posts with subjects" is enabled and the post is collapsed.
### Fixed
- Network fetches don't pile up anymore but wait for previous ones to finish to reduce throttling.
- Autocomplete won't stop at the second @, so it'll still work with "@lain@l" and not start over.
- Fixed weird autocomplete behavior when you write ":custom_emoji: ?"
## [2.1.0] - 2020-08-28
### Added
- Autocomplete domains from list of known instances
- 'Bot' settings option and badge
- Added profile meta data fields that can be set in profile settings
- Added option to reset avatar/banner in profile settings
- Descriptions can be set on uploaded files before posting
- Added status preview option to preview your statuses before posting
- When a post is a reply to an unavailable post, the 'Reply to'-text has a strike-through style
- Added ability to see all favoriting or repeating users when hovering the number on highlighted statuses
- Bookmarks
### Changed
- Change heart to thumbs up in reaction picker
- Close the media modal on navigation events
- Add colons to the emoji alt text, to make them copyable
- Add better visual indication for drag-and-drop for files
- When disabling attachments, the placeholder links now show an icon and the description instead of just IMAGE or VIDEO etc
- Remove unnecessary options for 'automatic loading when loading older' and 'reply previews'
- Greentext now has separate color slot for it
- Removed the use of with_move parameters when fetching notifications
- Push notifications now are the same as normal notfication, and are localized.
- Updated Notification Settings to match new BE API
### Fixed
- Custom Emoji will display in poll options now.
- Status ellipsis menu closes properly when selecting certain options
- Cropped images look correct in Chrome
- Newlines in the muted words settings work again
- Clicking on non-latin hashtags won't open a new window
- Uploading and drag-dropping multiple files works correctly now.
- Subject field now appears disabled when posting
- Fix status ellipsis menu being cut off in notifications column
- Fixed autocomplete sometimes not returning the right user when there's already some results
- Videos and audio and misc files show description as alt/title properly now
- Clicking on non-image/video files no longer opens an empty modal
- Audio files can now be played back in the frontend with hidden attachments
- Videos are not cropped awkwardly in the uploads section anymore
- Reply filtering options in Settings -> Filtering now work again using filtering on server
- Don't show just blank-screen when cookies are disabled
- Add status idempotency to prevent accidental double posting when posting returns an error
- Weird bug related to post being sent seemingly after pasting with keyboard (hopefully)
- Multiple issues with muted statuses/notifications
## [2.0.5] - 2020-05-12
### Added
- Added private notifications option for push notifications
- 'Copy link' button for statuses (in the ellipsis menu)
### Changed
- Registration page no longer requires email if the server is configured not to require it
### Fixed
- Status ellipsis menu closes properly when selecting certain options
## [2.0.3] - 2020-05-02
### Fixed
- Show more/less works correctly with auto-collapsed subjects and long posts
- RTL characters won't look messed up in notifications
### Changed
- Emoji autocomplete will match any part of the word and not just start, for example :drool will now helpfully suggest :blobcatdrool: and :blobcatdroolreach:
### Added
- Follow request notification support
## [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)
- Paper theme by Shpuld
- Icons in nav panel
- Private mode support
- Support for 'Move' type notifications
- Pleroma AMOLED dark theme
- User level domain mutes, under User Settings -> Mutes
- 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
- when using `--variable` in shadows it no longer uses the actual CSS3 variable, instead it generates color from other slots
- theme doesn't get saved to local storage when opening FE anonymously
- Captcha now resets on failed registrations
- 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
- Ability to hide/show repeats from user
- User profile button clutter organized into a menu
- Emoji picker
- Started changelog anew
- Ability to change user's email
- About page
- Added remote user redirect
### Changed
- changed the way fading effects for user profile/long statuses works, now uses css-mask instead of gradient background hacks which weren't exactly compatible with semi-transparent themes
### Fixed
- improved hotkey behavior on autocomplete popup
diff --git a/src/components/favorite_button/favorite_button.js b/src/components/favorite_button/favorite_button.js
index c996cba21d..cf3378c905 100644
--- a/src/components/favorite_button/favorite_button.js
+++ b/src/components/favorite_button/favorite_button.js
@@ -1,46 +1,49 @@
import { mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faStar,
faPlus,
faMinus,
faCheck
} from '@fortawesome/free-solid-svg-icons'
import {
faStar as faStarRegular
} from '@fortawesome/free-regular-svg-icons'
library.add(
faStar,
faStarRegular,
faPlus,
faMinus,
faCheck
)
const FavoriteButton = {
props: ['status', 'loggedIn'],
data () {
return {
animated: false
}
},
methods: {
favorite () {
if (!this.status.favorited) {
this.$store.dispatch('favorite', { id: this.status.id })
} else {
this.$store.dispatch('unfavorite', { id: this.status.id })
}
this.animated = true
setTimeout(() => {
this.animated = false
}, 500)
}
},
computed: {
- ...mapGetters(['mergedConfig'])
+ ...mapGetters(['mergedConfig']),
+ remoteInteractionLink () {
+ return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
+ }
}
}
export default FavoriteButton
diff --git a/src/components/favorite_button/favorite_button.vue b/src/components/favorite_button/favorite_button.vue
index 74a1dfbb45..ea01720a78 100644
--- a/src/components/favorite_button/favorite_button.vue
+++ b/src/components/favorite_button/favorite_button.vue
@@ -1,103 +1,109 @@
<template>
<div class="FavoriteButton">
<button
v-if="loggedIn"
class="button-unstyled interactive"
:class="status.favorited && '-favorited'"
:title="$t('tool_tip.favorite')"
@click.prevent="favorite()"
>
<FALayers class="fa-scale-110 fa-old-padding-layer">
<FAIcon
class="fa-scale-110"
:icon="[status.favorited ? 'fas' : 'far', 'star']"
:spin="animated"
/>
<FAIcon
v-if="status.favorited"
class="active-marker"
transform="shrink-6 up-9 right-12"
icon="check"
/>
<FAIcon
v-if="!status.favorited"
class="focus-marker"
transform="shrink-6 up-9 right-12"
icon="plus"
/>
<FAIcon
v-else
class="focus-marker"
transform="shrink-6 up-9 right-12"
icon="minus"
/>
</FALayers>
</button>
- <span v-else>
+ <a
+ v-else
+ class="button-unstyled interactive"
+ target="_blank"
+ role="button"
+ :href="remoteInteractionLink"
+ >
<FAIcon
class="fa-scale-110 fa-old-padding"
:title="$t('tool_tip.favorite')"
:icon="['far', 'star']"
/>
- </span>
+ </a>
<span
v-if="!mergedConfig.hidePostStats && status.fave_num > 0"
class="action-counter"
>
{{ status.fave_num }}
</span>
</div>
</template>
<script src="./favorite_button.js"></script>
<style lang="scss">
@import '../../_variables.scss';
@import '../../_mixins.scss';
.FavoriteButton {
display: flex;
> :first-child {
padding: 10px;
margin: -10px -8px -10px -10px;
}
.action-counter {
pointer-events: none;
user-select: none;
}
.interactive {
.svg-inline--fa {
animation-duration: 0.6s;
}
&:hover .svg-inline--fa,
&.-favorited .svg-inline--fa {
color: $fallback--cOrange;
color: var(--cOrange, $fallback--cOrange);
}
@include unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include focused-style {
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
}
</style>
diff --git a/src/components/reply_button/reply_button.js b/src/components/reply_button/reply_button.js
index d6382982da..543d25ac2d 100644
--- a/src/components/reply_button/reply_button.js
+++ b/src/components/reply_button/reply_button.js
@@ -1,24 +1,27 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faReply,
faPlus,
faTimes
} from '@fortawesome/free-solid-svg-icons'
library.add(
faReply,
faPlus,
faTimes
)
const ReplyButton = {
name: 'ReplyButton',
props: ['status', 'replying'],
computed: {
loggedIn () {
return !!this.$store.state.users.currentUser
+ },
+ remoteInteractionLink () {
+ return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
}
}
}
export default ReplyButton
diff --git a/src/components/reply_button/reply_button.vue b/src/components/reply_button/reply_button.vue
index ea97fbaad2..dada511bec 100644
--- a/src/components/reply_button/reply_button.vue
+++ b/src/components/reply_button/reply_button.vue
@@ -1,85 +1,91 @@
<template>
<div class="ReplyButton">
<button
v-if="loggedIn"
class="button-unstyled interactive"
:class="{'-active': replying}"
:title="$t('tool_tip.reply')"
@click.prevent="$emit('toggle')"
>
<FALayers class="fa-old-padding-layer">
<FAIcon
class="fa-scale-110"
icon="reply"
/>
<FAIcon
v-if="!replying"
class="focus-marker"
transform="shrink-6 up-8 right-11"
icon="plus"
/>
<FAIcon
v-else
class="focus-marker"
transform="shrink-6 up-8 right-11"
icon="times"
/>
</FALayers>
</button>
- <span v-else>
+ <a
+ v-else
+ class="button-unstyled interactive"
+ target="_blank"
+ role="button"
+ :href="remoteInteractionLink"
+ >
<FAIcon
icon="reply"
class="fa-scale-110 fa-old-padding"
:title="$t('tool_tip.reply')"
/>
- </span>
+ </a>
<span
v-if="status.replies_count > 0"
class="action-counter"
>
{{ status.replies_count }}
</span>
</div>
</template>
<script src="./reply_button.js"></script>
<style lang="scss">
@import '../../_variables.scss';
@import '../../_mixins.scss';
.ReplyButton {
display: flex;
> :first-child {
padding: 10px;
margin: -10px -8px -10px -10px;
}
.action-counter {
pointer-events: none;
user-select: none;
}
.interactive {
&:hover .svg-inline--fa,
&.-active .svg-inline--fa {
color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue);
}
@include unfocused-style {
.focus-marker {
visibility: hidden;
}
}
@include focused-style {
.focus-marker {
visibility: visible;
}
}
}
}
</style>
diff --git a/src/components/retweet_button/retweet_button.js b/src/components/retweet_button/retweet_button.js
index b7911814b8..4d92b5fa75 100644
--- a/src/components/retweet_button/retweet_button.js
+++ b/src/components/retweet_button/retweet_button.js
@@ -1,43 +1,46 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faRetweet,
faPlus,
faMinus,
faCheck
} from '@fortawesome/free-solid-svg-icons'
library.add(
faRetweet,
faPlus,
faMinus,
faCheck
)
const RetweetButton = {
props: ['status', 'loggedIn', 'visibility'],
data () {
return {
animated: false
}
},
methods: {
retweet () {
if (!this.status.repeated) {
this.$store.dispatch('retweet', { id: this.status.id })
} else {
this.$store.dispatch('unretweet', { id: this.status.id })
}
this.animated = true
setTimeout(() => {
this.animated = false
}, 500)
}
},
computed: {
mergedConfig () {
return this.$store.getters.mergedConfig
+ },
+ remoteInteractionLink () {
+ return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
}
}
}
export default RetweetButton
diff --git a/src/components/retweet_button/retweet_button.vue b/src/components/retweet_button/retweet_button.vue
index 396d1200bd..240828e3da 100644
--- a/src/components/retweet_button/retweet_button.vue
+++ b/src/components/retweet_button/retweet_button.vue
@@ -1,110 +1,116 @@
<template>
<div class="RetweetButton">
<button
v-if="visibility !== 'private' && visibility !== 'direct' && loggedIn"
class="button-unstyled interactive"
:class="status.repeated && '-repeated'"
:title="$t('tool_tip.repeat')"
@click.prevent="retweet()"
>
<FALayers class="fa-old-padding-layer">
<FAIcon
class="fa-scale-110"
icon="retweet"
:spin="animated"
/>
<FAIcon
v-if="status.repeated"
class="active-marker"
transform="shrink-6 up-9 right-12"
icon="check"
/>
<FAIcon
v-if="!status.repeated"
class="focus-marker"
transform="shrink-6 up-9 right-12"
icon="plus"
/>
<FAIcon
v-else
class="focus-marker"
transform="shrink-6 up-9 right-12"
icon="minus"
/>
</FALayers>
</button>
<span v-else-if="loggedIn">
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="lock"
:title="$t('timeline.no_retweet_hint')"
/>
</span>
- <span v-else>
+ <a
+ v-else
+ class="button-unstyled interactive"
+ target="_blank"
+ role="button"
+ :href="remoteInteractionLink"
+ >
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="retweet"
:title="$t('tool_tip.repeat')"
/>
- </span>
+ </a>
<span
v-if="!mergedConfig.hidePostStats && status.repeat_num > 0"
class="no-event"
>
{{ status.repeat_num }}
</span>
</div>
</template>
<script src="./retweet_button.js"></script>
<style lang="scss">
@import '../../_variables.scss';
@import '../../_mixins.scss';
.RetweetButton {
display: flex;
> :first-child {
padding: 10px;
margin: -10px -8px -10px -10px;
}
.action-counter {
pointer-events: none;
user-select: none;
}
.interactive {
.svg-inline--fa {
animation-duration: 0.6s;
}
&:hover .svg-inline--fa,
&.-repeated .svg-inline--fa {
color: $fallback--cGreen;
color: var(--cGreen, $fallback--cGreen);
}
@include unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include focused-style {
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
}
</style>
diff --git a/src/modules/instance.js b/src/modules/instance.js
index b1bc9779cf..3b15e62e36 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -1,348 +1,362 @@
import { getPreset, applyTheme } from '../services/style_setter/style_setter.js'
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
import apiService from '../services/api/api.service.js'
import { instanceDefaultProperties } from './config.js'
import { langCodeToCldrName, ensureFinalFallback } from '../i18n/languages.js'
const SORTED_EMOJI_GROUP_IDS = [
'smileys-and-emotion',
'people-and-body',
'animals-and-nature',
'food-and-drink',
'travel-and-places',
'activities',
'objects',
'symbols',
'flags'
]
const REGIONAL_INDICATORS = (() => {
const start = 0x1F1E6
const end = 0x1F1FF
const A = 'A'.codePointAt(0)
const res = new Array(end - start + 1)
for (let i = start; i <= end; ++i) {
const letter = String.fromCodePoint(A + i - start)
res[i - start] = {
replacement: String.fromCodePoint(i),
imageUrl: false,
displayText: 'regional_indicator_' + letter,
displayTextI18n: {
key: 'emoji.regional_indicator',
args: { letter }
}
}
}
return res
})()
+const REMOTE_INTERACTION_URL = '/main/ostatus'
+
const defaultState = {
// Stuff from apiConfig
name: 'Pleroma FE',
registrationOpen: true,
server: 'http://localhost:4040/',
textlimit: 5000,
themeData: undefined,
vapidPublicKey: undefined,
// Stuff from static/config.json
alwaysShowSubjectInput: true,
defaultAvatar: '/images/avi.png',
defaultBanner: '/images/banner.png',
background: '/static/aurora_borealis.jpg',
collapseMessageWithSubject: false,
greentext: false,
useAtIcon: false,
mentionLinkDisplay: 'short',
mentionLinkShowTooltip: true,
mentionLinkShowAvatar: false,
mentionLinkFadeDomain: true,
mentionLinkShowYous: false,
mentionLinkBoldenYou: true,
hideFilteredStatuses: false,
// bad name: actually hides posts of muted USERS
hideMutedPosts: false,
hideMutedThreads: true,
hideWordFilteredPosts: false,
hidePostStats: false,
hideBotIndication: false,
hideSitename: false,
hideUserStats: false,
muteBotStatuses: false,
loginMethod: 'password',
logo: '/static/logo.svg',
logoMargin: '.2em',
logoMask: true,
logoLeft: false,
disableUpdateNotification: false,
minimalScopesMode: false,
nsfwCensorImage: undefined,
postContentType: 'text/plain',
redirectRootLogin: '/main/friends',
redirectRootNoLogin: '/main/all',
scopeCopy: true,
showFeaturesPanel: true,
showInstanceSpecificPanel: false,
sidebarRight: false,
subjectLineBehavior: 'email',
theme: 'pleroma-dark',
virtualScrolling: true,
sensitiveByDefault: false,
conversationDisplay: 'linear',
conversationTreeAdvanced: false,
conversationOtherRepliesButton: 'below',
conversationTreeFadeAncestors: false,
maxDepthInThread: 6,
// Nasty stuff
customEmoji: [],
customEmojiFetched: false,
emoji: {},
emojiFetched: false,
unicodeEmojiAnnotations: {},
pleromaBackend: true,
postFormats: [],
restrictedNicknames: [],
safeDM: true,
knownDomains: [],
// Feature-set, apparently, not everything here is reported...
shoutAvailable: false,
pleromaChatMessagesAvailable: false,
gopherAvailable: false,
mediaProxyAvailable: false,
suggestionsEnabled: false,
suggestionsWeb: '',
// Html stuff
instanceSpecificPanelContent: '',
tos: '',
// Version Information
backendVersion: '',
frontendVersion: '',
pollsAvailable: false,
pollLimits: {
max_options: 4,
max_option_chars: 255,
min_expiration: 60,
max_expiration: 60 * 60 * 24
}
}
const loadAnnotations = (lang) => {
return import(
/* webpackChunkName: "emoji-annotations/[request]" */
`@kazvmoe-infra/unicode-emoji-json/annotations/${langCodeToCldrName(lang)}.json`
)
.then(k => k.default)
}
const injectAnnotations = (emoji, annotations) => {
const availableLangs = Object.keys(annotations)
return {
...emoji,
annotations: availableLangs.reduce((acc, cur) => {
acc[cur] = annotations[cur][emoji.replacement]
return acc
}, {})
}
}
const injectRegionalIndicators = groups => {
groups.symbols.push(...REGIONAL_INDICATORS)
return groups
}
const instance = {
state: defaultState,
mutations: {
setInstanceOption (state, { name, value }) {
if (typeof value !== 'undefined') {
state[name] = value
}
},
setKnownDomains (state, domains) {
state.knownDomains = domains
},
setUnicodeEmojiAnnotations (state, { lang, annotations }) {
state.unicodeEmojiAnnotations[lang] = annotations
}
},
getters: {
instanceDefaultConfig (state) {
return instanceDefaultProperties
.map(key => [key, state[key]])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
},
groupedCustomEmojis (state) {
const packsOf = emoji => {
return emoji.tags
.filter(k => k.startsWith('pack:'))
.map(k => k.slice(5)) // remove 'pack:' prefix
}
return state.customEmoji
.reduce((res, emoji) => {
packsOf(emoji).forEach(packName => {
const packId = `custom-${packName}`
if (!res[packId]) {
res[packId] = ({
id: packId,
text: packName,
image: emoji.imageUrl,
emojis: []
})
}
res[packId].emojis.push(emoji)
})
return res
}, {})
},
standardEmojiList (state) {
return SORTED_EMOJI_GROUP_IDS
.map(groupId => (state.emoji[groupId] || []).map(k => injectAnnotations(k, state.unicodeEmojiAnnotations)))
.reduce((a, b) => a.concat(b), [])
},
standardEmojiGroupList (state) {
return SORTED_EMOJI_GROUP_IDS.map(groupId => ({
id: groupId,
emojis: (state.emoji[groupId] || []).map(k => injectAnnotations(k, state.unicodeEmojiAnnotations))
}))
},
instanceDomain (state) {
return new URL(state.server).hostname
+ },
+ remoteInteractionLink (state) {
+ const server = state.server.endsWith('/') ? state.server.slice(0, -1) : state.server
+ const link = server + REMOTE_INTERACTION_URL
+
+ return ({ statusId, nickname }) => {
+ if (statusId) {
+ return `${link}?status_id=${statusId}`
+ } else {
+ return `${link}?nickname=${nickname}`
+ }
+ }
}
},
actions: {
setInstanceOption ({ commit, dispatch }, { name, value }) {
commit('setInstanceOption', { name, value })
switch (name) {
case 'name':
dispatch('setPageTitle')
break
case 'shoutAvailable':
if (value) {
dispatch('initializeSocket')
}
break
case 'theme':
dispatch('setTheme', value)
break
}
},
async getStaticEmoji ({ commit }) {
try {
const values = (await import(/* webpackChunkName: 'emoji' */ '../../static/emoji.json')).default
const emoji = Object.keys(values).reduce((res, groupId) => {
res[groupId] = values[groupId].map(e => ({
displayText: e.slug,
imageUrl: false,
replacement: e.emoji
}))
return res
}, {})
commit('setInstanceOption', { name: 'emoji', value: injectRegionalIndicators(emoji) })
} catch (e) {
console.warn("Can't load static emoji")
console.warn(e)
}
},
loadUnicodeEmojiData ({ commit, state }, language) {
const langList = ensureFinalFallback(language)
return Promise.all(
langList
.map(async lang => {
if (!state.unicodeEmojiAnnotations[lang]) {
const annotations = await loadAnnotations(lang)
commit('setUnicodeEmojiAnnotations', { lang, annotations })
}
}))
},
async getCustomEmoji ({ commit, state }) {
try {
const res = await window.fetch('/api/pleroma/emoji.json')
if (res.ok) {
const result = await res.json()
const values = Array.isArray(result) ? Object.assign({}, ...result) : result
const caseInsensitiveStrCmp = (a, b) => {
const la = a.toLowerCase()
const lb = b.toLowerCase()
return la > lb ? 1 : (la < lb ? -1 : 0)
}
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 emoji = Object.entries(values).map(([key, value]) => {
const imageUrl = value.image_url
return {
displayText: key,
imageUrl: imageUrl ? state.server + imageUrl : value,
tags: imageUrl ? value.tags.sort((a, b) => a > b ? 1 : 0) : ['utf'],
replacement: `:${key}: `
}
// Technically could use tags but those are kinda useless right now,
// should have been "pack" field, that would be more useful
}).sort(byPackThenByName)
commit('setInstanceOption', { name: 'customEmoji', value: emoji })
} else {
throw (res)
}
} catch (e) {
console.warn("Can't load custom emojis")
console.warn(e)
}
},
setTheme ({ commit, rootState }, themeName) {
commit('setInstanceOption', { name: 'theme', value: themeName })
getPreset(themeName)
.then(themeData => {
commit('setInstanceOption', { name: 'themeData', value: themeData })
// No need to apply theme if there's user theme already
const { customTheme } = rootState.config
if (customTheme) return
// 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 }) {
if (!state.customEmojiFetched) {
state.customEmojiFetched = true
dispatch('getCustomEmoji')
}
if (!state.emojiFetched) {
state.emojiFetched = true
dispatch('getStaticEmoji')
}
},
async getKnownDomains ({ commit, rootState }) {
try {
const result = await apiService.fetchKnownDomains({
credentials: rootState.users.currentUser.credentials
})
commit('setKnownDomains', result)
} catch (e) {
console.warn("Can't load known domains")
console.warn(e)
}
}
}
}
export default instance

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 19, 11:25 AM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1769383
Default Alt Text
(37 KB)

Event Timeline