aboutsummaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/services')
-rw-r--r--src/services/api/api.service.js7
-rw-r--r--src/services/entity_normalizer/entity_normalizer.service.js14
-rw-r--r--src/services/notification_utils/notification_utils.js44
-rw-r--r--src/services/resettable_async_component.js32
-rw-r--r--src/services/status_parser/status_parser.js18
-rw-r--r--src/services/theme_data/pleromafe.js6
6 files changed, 108 insertions, 13 deletions
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 9c7530a2..dfffc291 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,6 +1,5 @@
import { each, map, concat, last, get } from 'lodash'
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
-import 'whatwg-fetch'
import { RegistrationError, StatusCodeError } from '../errors/errors'
/* eslint-env browser */
@@ -75,6 +74,7 @@ const MASTODON_SEARCH_2 = `/api/v2/search`
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
const MASTODON_STREAMING = '/api/v1/streaming'
+const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions`
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
@@ -995,6 +995,10 @@ const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
})
}
+const fetchKnownDomains = ({ credentials }) => {
+ return promisedRequest({ url: MASTODON_KNOWN_DOMAIN_LIST_URL, credentials })
+}
+
const fetchDomainMutes = ({ credentials }) => {
return promisedRequest({ url: MASTODON_DOMAIN_BLOCKS_URL, credentials })
}
@@ -1193,6 +1197,7 @@ const apiService = {
updateNotificationSettings,
search2,
searchUsers,
+ fetchKnownDomains,
fetchDomainMutes,
muteDomain,
unmuteDomain
diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index 6dac7c15..3bdb92f3 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -56,6 +56,12 @@ export const parseUser = (data) => {
value: addEmojis(field.value, data.emojis)
}
})
+ output.fields_text = data.fields.map(field => {
+ return {
+ name: unescape(field.name.replace(/<[^>]*>/g, '')),
+ value: unescape(field.value.replace(/<[^>]*>/g, ''))
+ }
+ })
// Utilize avatar_static for gif avatars?
output.profile_image_url = data.avatar
@@ -210,7 +216,7 @@ export const addEmojis = (string, emojis) => {
const regexSafeShortCode = emoji.shortcode.replace(matchOperatorsRegex, '\\$&')
return acc.replace(
new RegExp(`:${regexSafeShortCode}:`, 'g'),
- `<img src='${emoji.url}' alt='${emoji.shortcode}' title='${emoji.shortcode}' class='emoji' />`
+ `<img src='${emoji.url}' alt=':${emoji.shortcode}:' title=':${emoji.shortcode}:' class='emoji' />`
)
}, string)
}
@@ -258,6 +264,12 @@ export const parseStatus = (data) => {
output.summary_html = addEmojis(escape(data.spoiler_text), data.emojis)
output.external_url = data.url
output.poll = data.poll
+ if (output.poll) {
+ output.poll.options = (output.poll.options || []).map(field => ({
+ ...field,
+ title_html: addEmojis(field.title, data.emojis)
+ }))
+ }
output.pinned = data.pinned
output.muted = data.muted
} else {
diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js
index eb479227..5cc19215 100644
--- a/src/services/notification_utils/notification_utils.js
+++ b/src/services/notification_utils/notification_utils.js
@@ -43,3 +43,47 @@ export const filteredNotificationsFromStore = (store, types) => {
export const unseenNotificationsFromStore = store =>
filter(filteredNotificationsFromStore(store), ({ seen }) => !seen)
+
+export const prepareNotificationObject = (notification, i18n) => {
+ const notifObj = {
+ tag: notification.id
+ }
+ const status = notification.status
+ const title = notification.from_profile.name
+ notifObj.title = title
+ notifObj.icon = notification.from_profile.profile_image_url
+ let i18nString
+ switch (notification.type) {
+ case 'like':
+ i18nString = 'favorited_you'
+ break
+ case 'repeat':
+ i18nString = 'repeated_you'
+ break
+ case 'follow':
+ i18nString = 'followed_you'
+ break
+ case 'move':
+ i18nString = 'migrated_to'
+ break
+ case 'follow_request':
+ i18nString = 'follow_request'
+ break
+ }
+
+ if (notification.type === 'pleroma:emoji_reaction') {
+ notifObj.body = i18n.t('notifications.reacted_with', [notification.emoji])
+ } else if (i18nString) {
+ notifObj.body = i18n.t('notifications.' + i18nString)
+ } else if (isStatusNotification(notification.type)) {
+ notifObj.body = notification.status.text
+ }
+
+ // Shows first attached non-nsfw image, if any. Should add configuration for this somehow...
+ if (status && status.attachments && status.attachments.length > 0 && !status.nsfw &&
+ status.attachments[0].mimetype.startsWith('image/')) {
+ notifObj.image = status.attachments[0].url
+ }
+
+ return notifObj
+}
diff --git a/src/services/resettable_async_component.js b/src/services/resettable_async_component.js
new file mode 100644
index 00000000..517bbd88
--- /dev/null
+++ b/src/services/resettable_async_component.js
@@ -0,0 +1,32 @@
+import Vue from 'vue'
+
+/* By default async components don't have any way to recover, if component is
+ * failed, it is failed forever. This helper tries to remedy that by recreating
+ * async component when retry is requested (by user). You need to emit the
+ * `resetAsyncComponent` event from child to reset the component. Generally,
+ * this should be done from error component but could be done from loading or
+ * actual target component itself if needs to be.
+ */
+function getResettableAsyncComponent (asyncComponent, options) {
+ const asyncComponentFactory = () => () => ({
+ component: asyncComponent(),
+ ...options
+ })
+
+ const observe = Vue.observable({ c: asyncComponentFactory() })
+
+ return {
+ functional: true,
+ render (createElement, { data, children }) {
+ // emit event resetAsyncComponent to reloading
+ data.on = {}
+ data.on.resetAsyncComponent = () => {
+ observe.c = asyncComponentFactory()
+ // parent.$forceUpdate()
+ }
+ return createElement(observe.c, data, children)
+ }
+ }
+}
+
+export default getResettableAsyncComponent
diff --git a/src/services/status_parser/status_parser.js b/src/services/status_parser/status_parser.js
index 900cd56e..ed0f6d57 100644
--- a/src/services/status_parser/status_parser.js
+++ b/src/services/status_parser/status_parser.js
@@ -1,15 +1,11 @@
-import sanitize from 'sanitize-html'
+import { filter } from 'lodash'
-export const removeAttachmentLinks = (html) => {
- return sanitize(html, {
- allowedTags: false,
- allowedAttributes: false,
- exclusiveFilter: ({ tag, attribs }) => tag === 'a' && typeof attribs.class === 'string' && attribs.class.match(/attachment/)
+export const muteWordHits = (status, muteWords) => {
+ const statusText = status.text.toLowerCase()
+ const statusSummary = status.summary.toLowerCase()
+ const hits = filter(muteWords, (muteWord) => {
+ return statusText.includes(muteWord.toLowerCase()) || statusSummary.includes(muteWord.toLowerCase())
})
-}
-export const parse = (html) => {
- return removeAttachmentLinks(html)
+ return hits
}
-
-export default parse
diff --git a/src/services/theme_data/pleromafe.js b/src/services/theme_data/pleromafe.js
index 0c1fe543..b577cfab 100644
--- a/src/services/theme_data/pleromafe.js
+++ b/src/services/theme_data/pleromafe.js
@@ -356,6 +356,12 @@ export const SLOT_INHERITANCE = {
textColor: 'preserve'
},
+ postGreentext: {
+ depends: ['cGreen'],
+ layer: 'bg',
+ textColor: 'preserve'
+ },
+
border: {
depends: ['fg'],
opacity: 'border',