diff options
Diffstat (limited to 'src/services')
| -rw-r--r-- | src/services/api/api.service.js | 9 | ||||
| -rw-r--r-- | src/services/chat_service/chat_service.js | 2 | ||||
| -rw-r--r-- | src/services/entity_normalizer/entity_normalizer.service.js | 16 | ||||
| -rw-r--r-- | src/services/favicon_service/favicon_service.js | 61 | ||||
| -rw-r--r-- | src/services/notifications_fetcher/notifications_fetcher.service.js | 18 | ||||
| -rw-r--r-- | src/services/theme_data/pleromafe.js | 4 | ||||
| -rw-r--r-- | src/services/timeline_fetcher/timeline_fetcher.service.js | 18 |
7 files changed, 109 insertions, 19 deletions
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 22b5e8ba..f4483149 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -162,7 +162,12 @@ const updateProfileImages = ({ credentials, avatar = null, banner = null, backgr body: form }) .then((data) => data.json()) - .then((data) => parseUser(data)) + .then((data) => { + if (data.error) { + throw new Error(data.error) + } + return parseUser(data) + }) } const updateProfile = ({ credentials, params }) => { @@ -560,7 +565,7 @@ const fetchTimeline = ({ }) .then((data) => data.json()) .then((data) => { - if (!data.error) { + if (!data.errors) { return { data: data.map(isNotifications ? parseNotification : parseStatus), pagination } } else { data.status = status diff --git a/src/services/chat_service/chat_service.js b/src/services/chat_service/chat_service.js index 1fc4e390..e653ebc1 100644 --- a/src/services/chat_service/chat_service.js +++ b/src/services/chat_service/chat_service.js @@ -21,7 +21,7 @@ const clear = (storage) => { failedMessageIds.push(message.id) } else { delete storage.idIndex[message.id] - delete storage.idempotencyKeyIndex[message.id] + delete storage.idempotencyKeyIndex[message.idempotency_key] } } diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 9d09b8d0..b1e68df5 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -2,6 +2,15 @@ import escape from 'escape-html' import parseLinkHeader from 'parse-link-header' import { isStatusNotification } from '../notification_utils/notification_utils.js' +/** NOTICE! ** + * Do not initialize UI-generated data here. + * It will override existing data. + * + * i.e. user.pinnedStatusIds was set to [] here + * UI code would update it with data but upon next user fetch + * it would be reverted back to [] + */ + const qvitterStatusType = (status) => { if (status.is_post_verb) { return 'status' @@ -53,7 +62,7 @@ export const parseUser = (data) => { output.fields = data.fields output.fields_html = data.fields.map(field => { return { - name: addEmojis(field.name, data.emojis), + name: addEmojis(escape(field.name), data.emojis), value: addEmojis(field.value, data.emojis) } }) @@ -173,9 +182,6 @@ export const parseUser = (data) => { output.locked = data.locked output.followers_count = data.followers_count output.statuses_count = data.statuses_count - output.friendIds = [] - output.followerIds = [] - output.pinnedStatusIds = [] if (data.pleroma) { output.follow_request_count = data.pleroma.follow_request_count @@ -274,7 +280,7 @@ export const parseStatus = (data) => { if (output.poll) { output.poll.options = (output.poll.options || []).map(field => ({ ...field, - title_html: addEmojis(field.title, data.emojis) + title_html: addEmojis(escape(field.title), data.emojis) })) } output.pinned = data.pinned diff --git a/src/services/favicon_service/favicon_service.js b/src/services/favicon_service/favicon_service.js new file mode 100644 index 00000000..d1ddee41 --- /dev/null +++ b/src/services/favicon_service/favicon_service.js @@ -0,0 +1,61 @@ +import { find } from 'lodash' + +const createFaviconService = () => { + let favimg, favcanvas, favcontext, favicon + const faviconWidth = 128 + const faviconHeight = 128 + const badgeRadius = 32 + + const initFaviconService = () => { + const nodes = document.getElementsByTagName('link') + favicon = find(nodes, node => node.rel === 'icon') + if (favicon) { + favcanvas = document.createElement('canvas') + favcanvas.width = faviconWidth + favcanvas.height = faviconHeight + favimg = new Image() + favimg.src = favicon.href + favcontext = favcanvas.getContext('2d') + } + } + + const isImageLoaded = (img) => img.complete && img.naturalHeight !== 0 + + const clearFaviconBadge = () => { + if (!favimg || !favcontext || !favicon) return + + favcontext.clearRect(0, 0, faviconWidth, faviconHeight) + if (isImageLoaded(favimg)) { + favcontext.drawImage(favimg, 0, 0, favimg.width, favimg.height, 0, 0, faviconWidth, faviconHeight) + } + favicon.href = favcanvas.toDataURL('image/png') + } + + const drawFaviconBadge = () => { + if (!favimg || !favcontext || !favcontext) return + + clearFaviconBadge() + + const style = getComputedStyle(document.body) + const badgeColor = `${style.getPropertyValue('--badgeNotification') || 'rgb(240, 100, 100)'}` + + if (isImageLoaded(favimg)) { + favcontext.drawImage(favimg, 0, 0, favimg.width, favimg.height, 0, 0, faviconWidth, faviconHeight) + } + favcontext.fillStyle = badgeColor + favcontext.beginPath() + favcontext.arc(faviconWidth - badgeRadius, badgeRadius, badgeRadius, 0, 2 * Math.PI, false) + favcontext.fill() + favicon.href = favcanvas.toDataURL('image/png') + } + + return { + initFaviconService, + clearFaviconBadge, + drawFaviconBadge + } +} + +const FaviconService = createFaviconService() + +export default FaviconService diff --git a/src/services/notifications_fetcher/notifications_fetcher.service.js b/src/services/notifications_fetcher/notifications_fetcher.service.js index 6ff7d9df..5f9c1e5e 100644 --- a/src/services/notifications_fetcher/notifications_fetcher.service.js +++ b/src/services/notifications_fetcher/notifications_fetcher.service.js @@ -2,7 +2,6 @@ import apiService from '../api/api.service.js' import { promiseInterval } from '../promise_interval/promise_interval.js' const update = ({ store, notifications, older }) => { - store.dispatch('setNotificationsError', { value: false }) store.dispatch('addNewNotifications', { notifications, older }) } @@ -50,11 +49,22 @@ const fetchAndUpdate = ({ store, credentials, older = false }) => { const fetchNotifications = ({ store, args, older }) => { return apiService.fetchTimeline(args) - .then(({ data: notifications }) => { + .then((response) => { + if (response.errors) { + throw new Error(`${response.status} ${response.statusText}`) + } + const notifications = response.data update({ store, notifications, older }) return notifications - }, () => store.dispatch('setNotificationsError', { value: true })) - .catch(() => store.dispatch('setNotificationsError', { value: true })) + }) + .catch((error) => { + store.dispatch('pushGlobalNotice', { + level: 'error', + messageKey: 'notifications.error', + messageArgs: [error.message], + timeout: 5000 + }) + }) } const startFetching = ({ credentials, store }) => { diff --git a/src/services/theme_data/pleromafe.js b/src/services/theme_data/pleromafe.js index 7ed85797..bec1eebd 100644 --- a/src/services/theme_data/pleromafe.js +++ b/src/services/theme_data/pleromafe.js @@ -84,6 +84,10 @@ export const SLOT_INHERITANCE = { opacity: 'bg', priority: 1 }, + wallpaper: { + depends: ['bg'], + color: (mod, bg) => brightness(-2 * mod, bg).rgb + }, fg: { depends: [], priority: 1 diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js index 72ea4890..921df3ed 100644 --- a/src/services/timeline_fetcher/timeline_fetcher.service.js +++ b/src/services/timeline_fetcher/timeline_fetcher.service.js @@ -6,9 +6,6 @@ import { promiseInterval } from '../promise_interval/promise_interval.js' const update = ({ store, statuses, timeline, showImmediately, userId, pagination }) => { const ccTimeline = camelCase(timeline) - store.dispatch('setError', { value: false }) - store.dispatch('setErrorData', { value: null }) - store.dispatch('addNewStatuses', { timeline: ccTimeline, userId, @@ -52,9 +49,8 @@ const fetchAndUpdate = ({ return apiService.fetchTimeline(args) .then(response => { - if (response.error) { - store.dispatch('setErrorData', { value: response }) - return + if (response.errors) { + throw new Error(`${response.status} ${response.statusText}`) } const { data: statuses, pagination } = response @@ -63,7 +59,15 @@ const fetchAndUpdate = ({ } update({ store, statuses, timeline, showImmediately, userId, pagination }) return { statuses, pagination } - }, () => store.dispatch('setError', { value: true })) + }) + .catch((error) => { + store.dispatch('pushGlobalNotice', { + level: 'error', + messageKey: 'timeline.error', + messageArgs: [error.message], + timeout: 5000 + }) + }) } const startFetching = ({ timeline = 'friends', credentials, store, userId = false, tag = false }) => { |
