fix conflicts, use file icon instead of link, add support for audio and file icon in cw'd posts

This commit is contained in:
Shpuld Shpuldson 2020-07-06 14:01:03 +03:00
commit 87b5f828d7
40 changed files with 455 additions and 63 deletions

View file

@ -1,5 +1,5 @@
import { each, map, concat, last, get } from 'lodash'
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
import { parseStatus, parseUser, parseNotification, parseAttachment, parseLinkHeaderPagination } from '../entity_normalizer/entity_normalizer.service.js'
import { RegistrationError, StatusCodeError } from '../errors/errors'
/* eslint-env browser */
@ -50,6 +50,7 @@ const MASTODON_USER_URL = '/api/v1/accounts'
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses`
const MASTODON_TAG_TIMELINE_URL = tag => `/api/v1/timelines/tag/${tag}`
const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks'
const MASTODON_USER_BLOCKS_URL = '/api/v1/blocks/'
const MASTODON_USER_MUTES_URL = '/api/v1/mutes/'
const MASTODON_BLOCK_USER_URL = id => `/api/v1/accounts/${id}/block`
@ -58,6 +59,8 @@ const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
const MASTODON_SUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/subscribe`
const MASTODON_UNSUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/unsubscribe`
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'
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
const MASTODON_VOTE_URL = id => `/api/v1/polls/${id}/votes`
@ -510,7 +513,8 @@ const fetchTimeline = ({
user: MASTODON_USER_TIMELINE_URL,
media: MASTODON_USER_TIMELINE_URL,
favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
tag: MASTODON_TAG_TIMELINE_URL
tag: MASTODON_TAG_TIMELINE_URL,
bookmarks: MASTODON_BOOKMARK_TIMELINE_URL
}
const isNotifications = timeline === 'notifications'
const params = []
@ -539,7 +543,7 @@ const fetchTimeline = ({
if (timeline === 'public' || timeline === 'publicAndExternal') {
params.push(['only_media', false])
}
if (timeline !== 'favorites') {
if (timeline !== 'favorites' && timeline !== 'bookmarks') {
params.push(['with_muted', withMuted])
}
if (replyVisibility !== 'all') {
@ -552,16 +556,20 @@ const fetchTimeline = ({
url += `?${queryString}`
let status = ''
let statusText = ''
let pagination = {}
return fetch(url, { headers: authHeaders(credentials) })
.then((data) => {
status = data.status
statusText = data.statusText
pagination = parseLinkHeaderPagination(data.headers.get('Link'), {
flakeId: timeline !== 'bookmarks' && timeline !== 'notifications'
})
return data
})
.then((data) => data.json())
.then((data) => {
if (!data.error) {
return data.map(isNotifications ? parseNotification : parseStatus)
return { data: data.map(isNotifications ? parseNotification : parseStatus), pagination }
} else {
data.status = status
data.statusText = statusText
@ -612,6 +620,22 @@ const unretweet = ({ id, credentials }) => {
.then((data) => parseStatus(data))
}
const bookmarkStatus = ({ id, credentials }) => {
return promisedRequest({
url: MASTODON_BOOKMARK_STATUS_URL(id),
headers: authHeaders(credentials),
method: 'POST'
})
}
const unbookmarkStatus = ({ id, credentials }) => {
return promisedRequest({
url: MASTODON_UNBOOKMARK_STATUS_URL(id),
headers: authHeaders(credentials),
method: 'POST'
})
}
const postStatus = ({
credentials,
status,
@ -1152,6 +1176,8 @@ const apiService = {
unfavorite,
retweet,
unretweet,
bookmarkStatus,
unbookmarkStatus,
postStatus,
deleteStatus,
uploadMedia,

View file

@ -12,10 +12,6 @@ const backendInteractorService = credentials => ({
return notificationsFetcher.startFetching({ store, credentials })
},
fetchAndUpdateNotifications ({ store }) {
return notificationsFetcher.fetchAndUpdate({ store, credentials })
},
startFetchingFollowRequests ({ store }) {
return followRequestFetcher.startFetching({ store, credentials })
},

View file

@ -1,4 +1,5 @@
import escape from 'escape-html'
import parseLinkHeader from 'parse-link-header'
import { isStatusNotification } from '../notification_utils/notification_utils.js'
const qvitterStatusType = (status) => {
@ -232,6 +233,8 @@ export const parseStatus = (data) => {
output.repeated = data.reblogged
output.repeat_num = data.reblogs_count
output.bookmarked = data.bookmarked
output.type = data.reblog ? 'retweet' : 'status'
output.nsfw = data.sensitive
@ -248,6 +251,7 @@ export const parseStatus = (data) => {
output.in_reply_to_screen_name = data.pleroma.in_reply_to_account_acct
output.thread_muted = pleroma.thread_muted
output.emoji_reactions = pleroma.emoji_reactions
output.parent_visible = pleroma.parent_visible === undefined ? true : pleroma.parent_visible
} else {
output.text = data.content
output.summary = data.spoiler_text
@ -381,3 +385,16 @@ const isNsfw = (status) => {
const nsfwRegex = /#nsfw/i
return (status.tags || []).includes('nsfw') || !!(status.text || '').match(nsfwRegex)
}
export const parseLinkHeaderPagination = (linkHeader, opts = {}) => {
const flakeId = opts.flakeId
const parsedLinkHeader = parseLinkHeader(linkHeader)
if (!parsedLinkHeader) return
const maxId = parsedLinkHeader.next.max_id
const minId = parsedLinkHeader.prev.min_id
return {
maxId: flakeId ? maxId : parseInt(maxId, 10),
minId: flakeId ? minId : parseInt(minId, 10)
}
}

View file

@ -4,6 +4,7 @@ const fetchAndUpdate = ({ store, credentials }) => {
return apiService.fetchFollowRequests({ credentials })
.then((requests) => {
store.commit('setFollowRequests', requests)
store.commit('addNewUsers', requests)
}, () => {})
.catch(() => {})
}

View file

@ -27,21 +27,25 @@ const fetchAndUpdate = ({ store, credentials, older = false }) => {
}
const result = fetchNotifications({ store, args, older })
// load unread notifications repeatedly to provide consistency between browser tabs
// If there's any unread notifications, try fetch notifications since
// the newest read notification to check if any of the unread notifs
// have changed their 'seen' state (marked as read in another session), so
// we can update the state in this session to mark them as read as well.
// The normal maxId-check does not tell if older notifications have changed
const notifications = timelineData.data
const readNotifsIds = notifications.filter(n => n.seen).map(n => n.id)
if (readNotifsIds.length) {
const numUnseenNotifs = notifications.length - readNotifsIds.length
if (numUnseenNotifs > 0) {
args['since'] = Math.max(...readNotifsIds)
fetchNotifications({ store, args, older })
}
return result
}
}
const fetchNotifications = ({ store, args, older }) => {
return apiService.fetchTimeline(args)
.then((notifications) => {
.then(({ data: notifications }) => {
update({ store, notifications, older })
return notifications
}, () => store.dispatch('setNotificationsError', { value: true }))

View file

@ -34,7 +34,8 @@ export const DEFAULT_OPACITY = {
alert: 0.5,
input: 0.5,
faint: 0.5,
underlay: 0.15
underlay: 0.15,
alertPopup: 0.95
}
/** SUBJECT TO CHANGE IN THE FUTURE, this is all beta
@ -627,6 +628,39 @@ export const SLOT_INHERITANCE = {
textColor: true
},
alertPopupError: {
depends: ['alertError'],
opacity: 'alertPopup'
},
alertPopupErrorText: {
depends: ['alertErrorText'],
layer: 'popover',
variant: 'alertPopupError',
textColor: true
},
alertPopupWarning: {
depends: ['alertWarning'],
opacity: 'alertPopup'
},
alertPopupWarningText: {
depends: ['alertWarningText'],
layer: 'popover',
variant: 'alertPopupWarning',
textColor: true
},
alertPopupNeutral: {
depends: ['alertNeutral'],
opacity: 'alertPopup'
},
alertPopupNeutralText: {
depends: ['alertNeutralText'],
layer: 'popover',
variant: 'alertPopupNeutral',
textColor: true
},
badgeNotification: '--cRed',
badgeNotificationText: {
depends: ['text', 'badgeNotification'],

View file

@ -2,7 +2,7 @@ import { camelCase } from 'lodash'
import apiService from '../api/api.service.js'
const update = ({ store, statuses, timeline, showImmediately, userId }) => {
const update = ({ store, statuses, timeline, showImmediately, userId, pagination }) => {
const ccTimeline = camelCase(timeline)
store.dispatch('setError', { value: false })
@ -12,7 +12,8 @@ const update = ({ store, statuses, timeline, showImmediately, userId }) => {
timeline: ccTimeline,
userId,
statuses,
showImmediately
showImmediately,
pagination
})
}
@ -47,16 +48,18 @@ const fetchAndUpdate = ({
const numStatusesBeforeFetch = timelineData.statuses.length
return apiService.fetchTimeline(args)
.then((statuses) => {
if (statuses.error) {
store.dispatch('setErrorData', { value: statuses })
.then(response => {
if (response.error) {
store.dispatch('setErrorData', { value: response })
return
}
const { data: statuses, pagination } = response
if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {
store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId })
}
update({ store, statuses, timeline, showImmediately, userId })
return statuses
update({ store, statuses, timeline, showImmediately, userId, pagination })
return { statuses, pagination }
}, () => store.dispatch('setError', { value: true }))
}