forked from AkkomaGang/akkoma-fe
Resolve merge conflict,
Fix few issues (conversation page highlight, fetch conversation, ...)
This commit is contained in:
commit
6143b1ce0f
11 changed files with 69 additions and 60 deletions
|
@ -1,5 +1,4 @@
|
|||
import Conversation from '../conversation/conversation.vue'
|
||||
import { find } from 'lodash'
|
||||
|
||||
const conversationPage = {
|
||||
components: {
|
||||
|
@ -8,8 +7,8 @@ const conversationPage = {
|
|||
computed: {
|
||||
statusoid () {
|
||||
const id = this.$route.params.id
|
||||
const statuses = this.$store.state.statuses.allStatuses
|
||||
const status = find(statuses, {id})
|
||||
const statuses = this.$store.state.statuses.allStatusesObject
|
||||
const status = statuses[id]
|
||||
|
||||
return status
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { reduce, filter, findIndex } from 'lodash'
|
||||
import { set } from 'vue'
|
||||
import Status from '../status/status.vue'
|
||||
|
||||
const sortById = (a, b) => {
|
||||
|
@ -26,7 +27,8 @@ const conversation = {
|
|||
data () {
|
||||
return {
|
||||
highlight: null,
|
||||
expanded: false
|
||||
expanded: false,
|
||||
converationStatusIds: []
|
||||
}
|
||||
},
|
||||
props: [
|
||||
|
@ -38,6 +40,15 @@ const conversation = {
|
|||
status () {
|
||||
return this.statusoid
|
||||
},
|
||||
idsToShow () {
|
||||
if (this.converationStatusIds.length > 0) {
|
||||
return this.converationStatusIds
|
||||
} else if (this.statusId) {
|
||||
return [this.statusId]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
},
|
||||
statusId () {
|
||||
if (this.statusoid.retweeted_status) {
|
||||
return this.statusoid.retweeted_status.id
|
||||
|
@ -54,14 +65,17 @@ const conversation = {
|
|||
return [this.status]
|
||||
}
|
||||
|
||||
const conversationId = this.status.statusnet_conversation_id
|
||||
const statuses = this.$store.state.statuses.allStatuses
|
||||
const conversation = filter(statuses, { statusnet_conversation_id: conversationId })
|
||||
const statusesObject = this.$store.state.statuses.allStatusesObject
|
||||
const conversation = this.idsToShow.reduce((acc, id) => {
|
||||
acc.push(statusesObject[id])
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
const statusIndex = findIndex(conversation, { id: this.statusId })
|
||||
if (statusIndex !== -1) {
|
||||
conversation[statusIndex] = this.status
|
||||
}
|
||||
|
||||
return sortAndFilterConversation(conversation)
|
||||
},
|
||||
replies () {
|
||||
|
@ -99,9 +113,15 @@ const conversation = {
|
|||
methods: {
|
||||
fetchConversation () {
|
||||
if (this.status) {
|
||||
const conversationId = this.status.statusnet_conversation_id
|
||||
this.$store.state.api.backendInteractor.fetchConversation({id: conversationId})
|
||||
.then((statuses) => this.$store.dispatch('addNewStatuses', { statuses }))
|
||||
this.$store.state.api.backendInteractor.fetchConversation({id: this.status.id})
|
||||
.then(({ancestors, descendants}) => {
|
||||
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
|
||||
this.$store.dispatch('addNewStatuses', { statuses: descendants })
|
||||
set(this, 'converationStatusIds', [].concat(
|
||||
ancestors.map(_ => _.id),
|
||||
this.statusId,
|
||||
descendants.map(_ => _.id)))
|
||||
})
|
||||
.then(() => this.setHighlight(this.statusId))
|
||||
} else {
|
||||
const id = this.$route.params.id
|
||||
|
|
|
@ -20,7 +20,7 @@ const mediaUpload = {
|
|||
return
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('media', file)
|
||||
formData.append('file', file)
|
||||
|
||||
self.$emit('uploading')
|
||||
self.uploading = true
|
||||
|
|
|
@ -296,6 +296,8 @@ const PostStatusForm = {
|
|||
},
|
||||
paste (e) {
|
||||
if (e.clipboardData.files.length > 0) {
|
||||
// prevent pasting of file as text
|
||||
e.preventDefault()
|
||||
// Strangely, files property gets emptied after event propagation
|
||||
// Trying to wrap it in array doesn't work. Plus I doubt it's possible
|
||||
// to hold more than one file in clipboard.
|
||||
|
|
|
@ -84,10 +84,10 @@
|
|||
<div class="media-upload-wrapper" v-for="file in newStatus.files">
|
||||
<i class="fa button-icon icon-cancel" @click="removeMediaFile(file)"></i>
|
||||
<div class="media-upload-container attachment">
|
||||
<img class="thumbnail media-upload" :src="file.image" v-if="type(file) === 'image'"></img>
|
||||
<video v-if="type(file) === 'video'" :src="file.image" controls></video>
|
||||
<audio v-if="type(file) === 'audio'" :src="file.image" controls></audio>
|
||||
<a v-if="type(file) === 'unknown'" :href="file.image">{{file.url}}</a>
|
||||
<img class="thumbnail media-upload" :src="file.url" v-if="type(file) === 'image'"></img>
|
||||
<video v-if="type(file) === 'video'" :src="file.url" controls></video>
|
||||
<audio v-if="type(file) === 'audio'" :src="file.url" controls></audio>
|
||||
<a v-if="type(file) === 'unknown'" :href="file.url">{{file.url}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -287,8 +287,6 @@
|
|||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: $fallback--avatarRadius;
|
||||
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@ export default function createPersistedState ({
|
|||
merge({}, store.state, savedState)
|
||||
)
|
||||
}
|
||||
if (store.state.oauth.token) {
|
||||
store.dispatch('loginUser', store.state.oauth.token)
|
||||
}
|
||||
loaded = true
|
||||
} catch (e) {
|
||||
console.log("Couldn't load state")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash'
|
||||
import { set } from 'vue'
|
||||
import apiService from '../services/api/api.service.js'
|
||||
// import parse from '../services/status_parser/status_parser.js'
|
||||
|
||||
|
@ -82,7 +83,7 @@ const mergeOrAdd = (arr, obj, item) => {
|
|||
// This is a new item, prepare it
|
||||
prepareStatus(item)
|
||||
arr.push(item)
|
||||
obj[item.id] = item
|
||||
set(obj, item.id, item)
|
||||
return {item, new: true}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ export const mergeOrAdd = (arr, obj, item) => {
|
|||
} else {
|
||||
// This is a new item, prepare it
|
||||
arr.push(item)
|
||||
obj[item.id] = item
|
||||
set(obj, item.id, item)
|
||||
if (item.screen_name && !item.screen_name.includes('@')) {
|
||||
obj[item.screen_name.toLowerCase()] = item
|
||||
set(obj, item.screen_name.toLowerCase(), item)
|
||||
}
|
||||
return { item, new: true }
|
||||
}
|
||||
|
|
|
@ -9,11 +9,7 @@ const FAVORITE_URL = '/api/favorites/create'
|
|||
const UNFAVORITE_URL = '/api/favorites/destroy'
|
||||
const RETWEET_URL = '/api/statuses/retweet'
|
||||
const UNRETWEET_URL = '/api/statuses/unretweet'
|
||||
const STATUS_UPDATE_URL = '/api/statuses/update.json'
|
||||
const STATUS_DELETE_URL = '/api/statuses/destroy'
|
||||
const STATUS_URL = '/api/statuses/show'
|
||||
const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload'
|
||||
const CONVERSATION_URL = '/api/statusnet/conversation'
|
||||
const MENTIONS_URL = '/api/statuses/mentions.json'
|
||||
const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
|
||||
const FOLLOWERS_URL = '/api/statuses/followers.json'
|
||||
|
@ -37,6 +33,8 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
|
|||
const SUGGESTIONS_URL = '/api/v1/suggestions'
|
||||
|
||||
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
|
||||
const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
|
||||
const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
|
||||
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`
|
||||
|
@ -46,9 +44,11 @@ const MASTODON_BLOCK_USER_URL = id => `/api/v1/accounts/${id}/block`
|
|||
const MASTODON_UNBLOCK_USER_URL = id => `/api/v1/accounts/${id}/unblock`
|
||||
const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
|
||||
const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
|
||||
const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
|
||||
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
|
||||
|
||||
import { each, map } from 'lodash'
|
||||
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
|
||||
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
||||
import 'whatwg-fetch'
|
||||
import { StatusCodeError } from '../errors/errors'
|
||||
|
||||
|
@ -317,8 +317,8 @@ const fetchFollowRequests = ({credentials}) => {
|
|||
}
|
||||
|
||||
const fetchConversation = ({id, credentials}) => {
|
||||
let url = `${CONVERSATION_URL}/${id}.json?count=100`
|
||||
return fetch(url, { headers: authHeaders(credentials) })
|
||||
let urlContext = MASTODON_STATUS_CONTEXT_URL(id)
|
||||
return fetch(urlContext, { headers: authHeaders(credentials) })
|
||||
.then((data) => {
|
||||
if (data.ok) {
|
||||
return data
|
||||
|
@ -326,11 +326,14 @@ const fetchConversation = ({id, credentials}) => {
|
|||
throw new Error('Error fetching timeline', data)
|
||||
})
|
||||
.then((data) => data.json())
|
||||
.then((data) => data.map(parseStatus))
|
||||
.then(({ancestors, descendants}) => ({
|
||||
ancestors: ancestors.map(parseStatus),
|
||||
descendants: descendants.map(parseStatus)
|
||||
}))
|
||||
}
|
||||
|
||||
const fetchStatus = ({id, credentials}) => {
|
||||
let url = `${STATUS_URL}/${id}.json`
|
||||
let url = MASTODON_STATUS_URL(id)
|
||||
return fetch(url, { headers: authHeaders(credentials) })
|
||||
.then((data) => {
|
||||
if (data.ok) {
|
||||
|
@ -439,23 +442,23 @@ const unretweet = ({ id, credentials }) => {
|
|||
})
|
||||
}
|
||||
|
||||
const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType, noAttachmentLinks}) => {
|
||||
const idsText = mediaIds.join(',')
|
||||
const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds = [], inReplyToStatusId, contentType}) => {
|
||||
const form = new FormData()
|
||||
|
||||
form.append('status', status)
|
||||
form.append('source', 'Pleroma FE')
|
||||
if (noAttachmentLinks) form.append('no_attachment_links', noAttachmentLinks)
|
||||
if (spoilerText) form.append('spoiler_text', spoilerText)
|
||||
if (visibility) form.append('visibility', visibility)
|
||||
if (sensitive) form.append('sensitive', sensitive)
|
||||
if (contentType) form.append('content_type', contentType)
|
||||
form.append('media_ids', idsText)
|
||||
mediaIds.forEach(val => {
|
||||
form.append('media_ids[]', val)
|
||||
})
|
||||
if (inReplyToStatusId) {
|
||||
form.append('in_reply_to_status_id', inReplyToStatusId)
|
||||
form.append('in_reply_to_id', inReplyToStatusId)
|
||||
}
|
||||
|
||||
return fetch(STATUS_UPDATE_URL, {
|
||||
return fetch(MASTODON_POST_STATUS_URL, {
|
||||
body: form,
|
||||
method: 'POST',
|
||||
headers: authHeaders(credentials)
|
||||
|
@ -480,13 +483,13 @@ const deleteStatus = ({ id, credentials }) => {
|
|||
}
|
||||
|
||||
const uploadMedia = ({formData, credentials}) => {
|
||||
return fetch(MEDIA_UPLOAD_URL, {
|
||||
return fetch(MASTODON_MEDIA_UPLOAD_URL, {
|
||||
body: formData,
|
||||
method: 'POST',
|
||||
headers: authHeaders(credentials)
|
||||
})
|
||||
.then((response) => response.text())
|
||||
.then((text) => (new DOMParser()).parseFromString(text, 'application/xml'))
|
||||
.then((data) => data.json())
|
||||
.then((data) => parseAttachment(data))
|
||||
}
|
||||
|
||||
const followImport = ({params, credentials}) => {
|
||||
|
|
|
@ -128,14 +128,15 @@ export const parseUser = (data) => {
|
|||
return output
|
||||
}
|
||||
|
||||
const parseAttachment = (data) => {
|
||||
export const parseAttachment = (data) => {
|
||||
const output = {}
|
||||
const masto = !data.hasOwnProperty('oembed')
|
||||
|
||||
if (masto) {
|
||||
// Not exactly same...
|
||||
output.mimetype = data.type
|
||||
output.mimetype = data.pleroma ? data.pleroma.mime_type : data.type
|
||||
output.meta = data.meta // not present in BE yet
|
||||
output.id = data.id
|
||||
} else {
|
||||
output.mimetype = data.mimetype
|
||||
// output.meta = ??? missing
|
||||
|
|
|
@ -4,7 +4,7 @@ import apiService from '../api/api.service.js'
|
|||
const postStatus = ({ store, status, spoilerText, visibility, sensitive, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => {
|
||||
const mediaIds = map(media, 'id')
|
||||
|
||||
return apiService.postStatus({credentials: store.state.users.currentUser.credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType, noAttachmentLinks: store.state.instance.noAttachmentLinks})
|
||||
return apiService.postStatus({credentials: store.state.users.currentUser.credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType})
|
||||
.then((data) => {
|
||||
if (!data.error) {
|
||||
store.dispatch('addNewStatuses', {
|
||||
|
@ -26,25 +26,7 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, media =
|
|||
const uploadMedia = ({ store, formData }) => {
|
||||
const credentials = store.state.users.currentUser.credentials
|
||||
|
||||
return apiService.uploadMedia({ credentials, formData }).then((xml) => {
|
||||
// Firefox and Chrome treat method differently...
|
||||
let link = xml.getElementsByTagName('link')
|
||||
|
||||
if (link.length === 0) {
|
||||
link = xml.getElementsByTagName('atom:link')
|
||||
}
|
||||
|
||||
link = link[0]
|
||||
|
||||
const mediaData = {
|
||||
id: xml.getElementsByTagName('media_id')[0].textContent,
|
||||
url: xml.getElementsByTagName('media_url')[0].textContent,
|
||||
image: link.getAttribute('href'),
|
||||
mimetype: link.getAttribute('type')
|
||||
}
|
||||
|
||||
return mediaData
|
||||
})
|
||||
return apiService.uploadMedia({ credentials, formData })
|
||||
}
|
||||
|
||||
const statusPosterService = {
|
||||
|
|
Loading…
Reference in a new issue