diff --git a/changelog.d/akkoma-sharkey-net-support.add b/changelog.d/akkoma-sharkey-net-support.add
new file mode 100644
index 000000000..0e39a4145
--- /dev/null
+++ b/changelog.d/akkoma-sharkey-net-support.add
@@ -0,0 +1 @@
+Added support for Akkoma and Sharkey.NET backend (tested on Sharkey)
diff --git a/index.html b/index.html
index a2f928361..f279ed01a 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,7 @@
+
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index 1b133a089..39fc6f6f0 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -63,10 +63,11 @@ const getInstanceConfig = async ({ store }) => {
const textlimit = data.max_toot_chars
const vapidPublicKey = data.pleroma.vapid_public_key
+ store.dispatch('setInstanceOption', { name: 'pleromaExtensionsAvailable', value: data.pleroma })
store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit })
store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.approval_required })
- store.dispatch('setInstanceOption', { name: 'birthdayRequired', value: !!data.pleroma.metadata.birthday_required })
- store.dispatch('setInstanceOption', { name: 'birthdayMinAge', value: data.pleroma.metadata.birthday_min_age || 0 })
+ store.dispatch('setInstanceOption', { name: 'birthdayRequired', value: !!data.pleroma?.metadata.birthday_required })
+ store.dispatch('setInstanceOption', { name: 'birthdayMinAge', value: data.pleroma?.metadata.birthday_min_age || 0 })
if (vapidPublicKey) {
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
@@ -78,6 +79,8 @@ const getInstanceConfig = async ({ store }) => {
console.error('Could not load instance config, potentially fatal')
console.error(error)
}
+ // We should check for scrobbles support here but it requires userId
+ // so instead we check for it where it's fetched (statuses.js)
}
const getBackendProvidedConfig = async () => {
@@ -242,7 +245,8 @@ const resolveStaffAccounts = ({ store, accounts }) => {
const getNodeInfo = async ({ store }) => {
try {
- const res = await preloadFetch('/nodeinfo/2.1.json')
+ let res = await preloadFetch('/nodeinfo/2.1.json')
+ if (!res.ok) res = await preloadFetch('/nodeinfo/2.0.json')
if (res.ok) {
const data = await res.json()
const metadata = data.metadata
@@ -262,6 +266,7 @@ const getNodeInfo = async ({ store }) => {
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
store.dispatch('setInstanceOption', { name: 'quotingAvailable', value: features.includes('quote_posting') })
store.dispatch('setInstanceOption', { name: 'groupActorAvailable', value: features.includes('pleroma:group_actors') })
+ store.dispatch('setInstanceOption', { name: 'localBubbleInstances', value: metadata.localBubbleInstances ?? [] })
const uploadLimits = metadata.uploadLimits
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
@@ -280,7 +285,6 @@ const getNodeInfo = async ({ store }) => {
const software = data.software
store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
store.dispatch('setInstanceOption', { name: 'backendRepository', value: software.repository })
- store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' })
const priv = metadata.private
store.dispatch('setInstanceOption', { name: 'private', value: priv })
diff --git a/src/boot/routes.js b/src/boot/routes.js
index da87c6c61..02abf8ce6 100644
--- a/src/boot/routes.js
+++ b/src/boot/routes.js
@@ -1,4 +1,5 @@
import PublicTimeline from 'components/public_timeline/public_timeline.vue'
+import BubbleTimeline from 'components/bubble_timeline/bubble_timeline.vue'
import PublicAndExternalTimeline from 'components/public_and_external_timeline/public_and_external_timeline.vue'
import FriendsTimeline from 'components/friends_timeline/friends_timeline.vue'
import TagTimeline from 'components/tag_timeline/tag_timeline.vue'
@@ -54,6 +55,7 @@ export default (store) => {
{ name: 'friends', path: '/main/friends', component: FriendsTimeline, beforeEnter: validateAuthenticatedRoute },
{ name: 'tag-timeline', path: '/tag/:tag', component: TagTimeline },
{ name: 'bookmarks', path: '/bookmarks', component: BookmarkTimeline },
+ { name: 'bubble', path: '/bubble', component: BubbleTimeline },
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
{ name: 'quotes', path: '/notice/:id/quotes', component: QuotesTimeline },
{
diff --git a/src/components/bubble_timeline/bubble_timeline.js b/src/components/bubble_timeline/bubble_timeline.js
new file mode 100644
index 000000000..6f73dd2b8
--- /dev/null
+++ b/src/components/bubble_timeline/bubble_timeline.js
@@ -0,0 +1,18 @@
+import Timeline from '../timeline/timeline.vue'
+const BubbleTimeline = {
+ components: {
+ Timeline
+ },
+ computed: {
+ timeline () { return this.$store.state.statuses.timelines.bubble }
+ },
+ created () {
+ this.$store.dispatch('startFetchingTimeline', { timeline: 'bubble' })
+ },
+ unmounted () {
+ this.$store.dispatch('stopFetchingTimeline', 'bubble')
+ }
+
+}
+
+export default BubbleTimeline
diff --git a/src/components/bubble_timeline/bubble_timeline.vue b/src/components/bubble_timeline/bubble_timeline.vue
new file mode 100644
index 000000000..4aefa2729
--- /dev/null
+++ b/src/components/bubble_timeline/bubble_timeline.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index 681aaf05b..a155abe0c 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -15,6 +15,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import {
faUsers,
faGlobe,
+ faCity,
faBookmark,
faEnvelope,
faChevronDown,
@@ -31,6 +32,7 @@ import {
library.add(
faUsers,
faGlobe,
+ faCity,
faBookmark,
faEnvelope,
faChevronDown,
@@ -108,12 +110,15 @@ const NavPanel = {
privateMode: state => state.instance.private,
federating: state => state.instance.federating,
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
- bookmarkFolders: state => state.instance.pleromaBookmarkFoldersAvailable
+ bookmarkFolders: state => state.instance.pleromaBookmarkFoldersAvailable,
+ bubbleTimeline: state => state.instance.localBubbleInstances.length > 0
}),
timelinesItems () {
return filterNavigation(
Object
.entries({ ...TIMELINES })
+ // do not show in timeliens list since it's in a better place now
+ .filter(([key]) => key !== 'bookmarks')
.map(([k, v]) => ({ ...v, name: k })),
{
hasChats: this.pleromaChatMessagesAvailable,
@@ -121,6 +126,7 @@ const NavPanel = {
isFederating: this.federating,
isPrivate: this.privateMode,
currentUser: this.currentUser,
+ supportsBubbleTimeline: this.bubbleTimeline,
supportsBookmarkFolders: this.bookmarkFolders
}
)
@@ -136,6 +142,7 @@ const NavPanel = {
isFederating: this.federating,
isPrivate: this.privateMode,
currentUser: this.currentUser,
+ supportsBubbleTimeline: this.bubbleTimeline,
supportsBookmarkFolders: this.bookmarkFolders
}
)
diff --git a/src/components/navigation/filter.js b/src/components/navigation/filter.js
index 12ab9266e..54abb67b4 100644
--- a/src/components/navigation/filter.js
+++ b/src/components/navigation/filter.js
@@ -1,4 +1,12 @@
-export const filterNavigation = (list = [], { hasChats, hasAnnouncements, isFederating, isPrivate, currentUser, supportsBookmarkFolders }) => {
+export const filterNavigation = (list = [], {
+ hasChats,
+ hasAnnouncements,
+ isFederating,
+ isPrivate,
+ currentUser,
+ supportsBookmarkFolders,
+ supportsBubbleTimeline
+}) => {
return list.filter(({ criteria, anon, anonRoute }) => {
const set = new Set(criteria || [])
if (!isFederating && set.has('federating')) return false
@@ -7,6 +15,8 @@ export const filterNavigation = (list = [], { hasChats, hasAnnouncements, isFede
if ((!currentUser || !currentUser.locked) && set.has('lockedUser')) return false
if (!hasChats && set.has('chats')) return false
if (!hasAnnouncements && set.has('announcements')) return false
+ if (!supportsBubbleTimeline && set.has('supportsBubbleTimeline')) return false
+ if (!supportsBookmarkFolders && set.has('supportsBookmarkFolders')) return false
if (supportsBookmarkFolders && set.has('!supportsBookmarkFolders')) return false
return true
})
@@ -19,11 +29,11 @@ export const getListEntries = store => store.allLists.map(list => ({
iconLetter: list.title[0]
}))
-export const getBookmarkFolderEntries = store => store.allFolders.map(folder => ({
+export const getBookmarkFolderEntries = store => store.allFolders ? store.allFolders.map(folder => ({
name: 'bookmark-folder-' + folder.id,
routeObject: { name: 'bookmark-folder', params: { id: folder.id } },
labelRaw: folder.name,
iconEmoji: folder.emoji,
iconEmojiUrl: folder.emoji_url,
iconLetter: folder.name[0]
-}))
+})) : []
diff --git a/src/components/navigation/navigation.js b/src/components/navigation/navigation.js
index a8e1fc966..d1c2b6763 100644
--- a/src/components/navigation/navigation.js
+++ b/src/components/navigation/navigation.js
@@ -27,6 +27,13 @@ export const TIMELINES = {
label: 'nav.public_tl',
criteria: ['!private']
},
+ bubble: {
+ route: 'bubble',
+ anon: true,
+ icon: 'city',
+ label: 'nav.bubble',
+ criteria: ['!private', 'federating', 'supportsBubbleTimeline']
+ },
twkn: {
route: 'public-external-timeline',
anon: true,
@@ -34,11 +41,11 @@ export const TIMELINES = {
label: 'nav.twkn',
criteria: ['!private', 'federating']
},
+ // bookmarks are still technically a timeline so we should show it in the dropdown
bookmarks: {
route: 'bookmarks',
icon: 'bookmark',
label: 'nav.bookmarks',
- criteria: ['!supportsBookmarkFolders']
},
favorites: {
routeObject: { name: 'user-profile', query: { tab: 'favorites' } },
@@ -53,6 +60,15 @@ export const TIMELINES = {
}
export const ROOT_ITEMS = {
+ bookmarks: {
+ route: 'bookmarks',
+ icon: 'bookmark',
+ label: 'nav.bookmarks',
+ // shows bookmarks entry in a better suited location
+ // hides it when bookmark folders are supported since
+ // we show custom component instead of it
+ criteria: ['!supportsBookmarkFolders']
+ },
interactions: {
route: 'interactions',
icon: 'bell',
diff --git a/src/components/navigation/navigation_pins.js b/src/components/navigation/navigation_pins.js
index 50acbbaf1..f9a900fc6 100644
--- a/src/components/navigation/navigation_pins.js
+++ b/src/components/navigation/navigation_pins.js
@@ -9,6 +9,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import {
faUsers,
faGlobe,
+ faCity,
faBookmark,
faEnvelope,
faComments,
@@ -25,6 +26,7 @@ import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
library.add(
faUsers,
faGlobe,
+ faCity,
faBookmark,
faEnvelope,
faComments,
@@ -65,7 +67,8 @@ const NavPanel = {
followRequestCount: state => state.api.followRequests.length,
privateMode: state => state.instance.private,
federating: state => state.instance.federating,
- pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
+ pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
+ bubbleTimeline: state => state.instance.localBubbleInstances.length > 0
}),
pinnedList () {
if (!this.currentUser) {
@@ -79,7 +82,9 @@ const NavPanel = {
hasAnnouncements: this.supportsAnnouncements,
isFederating: this.federating,
isPrivate: this.privateMode,
- currentUser: this.currentUser
+ currentUser: this.currentUser,
+ supportsBubbleTimeline: this.bubbleTimeline,
+ supportsBookmarkFolders: this.bookmarks
})
}
return filterNavigation(
@@ -98,6 +103,8 @@ const NavPanel = {
{
hasChats: this.pleromaChatMessagesAvailable,
hasAnnouncements: this.supportsAnnouncements,
+ supportsBubbleTimeline: this.bubbleTimeline,
+ supportsBookmarkFolders: this.bookmarks,
isFederating: this.federating,
isPrivate: this.privateMode,
currentUser: this.currentUser
diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.js b/src/components/settings_modal/tabs/security_tab/security_tab.js
index 3cbc0c927..04e0328cd 100644
--- a/src/components/settings_modal/tabs/security_tab/security_tab.js
+++ b/src/components/settings_modal/tabs/security_tab/security_tab.js
@@ -41,8 +41,8 @@ const SecurityTab = {
user () {
return this.$store.state.users.currentUser
},
- pleromaBackend () {
- return this.$store.state.instance.pleromaBackend
+ pleromaExtensionsAvailable () {
+ return this.$store.state.instance.pleromaExtensionsAvailable
},
oauthTokens () {
return useOAuthTokensStore().tokens.map(oauthToken => {
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 7ee2632bd..ba6fe1b68 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -24,6 +24,7 @@ import {
faLock,
faLockOpen,
faGlobe,
+ faIgloo,
faTimes,
faRetweet,
faReply,
@@ -43,6 +44,7 @@ import {
library.add(
faEnvelope,
faGlobe,
+ faIgloo,
faLock,
faLockOpen,
faTimes,
@@ -484,6 +486,8 @@ const Status = {
return 'lock-open'
case 'direct':
return 'envelope'
+ case 'local':
+ return 'igloo'
default:
return 'globe'
}
diff --git a/src/components/timeline_menu/timeline_menu.js b/src/components/timeline_menu/timeline_menu.js
index 38e6bdf4f..4c8f7b76e 100644
--- a/src/components/timeline_menu/timeline_menu.js
+++ b/src/components/timeline_menu/timeline_menu.js
@@ -24,7 +24,8 @@ export const timelineNames = (supportsBookmarkFolders) => {
dms: 'nav.dms',
'public-timeline': 'nav.public_tl',
'public-external-timeline': 'nav.twkn',
- quotes: 'nav.quotes'
+ quotes: 'nav.quotes',
+ bubble: 'nav.bubble'
}
}
@@ -58,7 +59,8 @@ const TimelineMenu = {
currentUser: state => state.users.currentUser,
privateMode: state => state.instance.private,
federating: state => state.instance.federating,
- bookmarkFolders: state => state.instance.pleromaBookmarkFoldersAvailable
+ bookmarkFolders: state => state.instance.pleromaBookmarkFoldersAvailable,
+ bubbleTimeline: state => state.instance.localBubbleInstances.length > 0
}),
timelinesList () {
return filterNavigation(
@@ -68,7 +70,8 @@ const TimelineMenu = {
isFederating: this.federating,
isPrivate: this.privateMode,
currentUser: this.currentUser,
- supportsBookmarkFolders: this.bookmarkFolders
+ supportsBookmarkFolders: this.bookmarkFolders,
+ supportsBubbleTimeline: this.bubbleTimeline
}
)
}
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index be81b8ad5..55c76225c 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -134,7 +134,10 @@ export default {
},
showModerationMenu () {
const privileges = this.loggedIn.privileges
- return this.loggedIn.role === 'admin' || privileges.includes('users_manage_activation_state') || privileges.includes('users_delete') || privileges.includes('users_manage_tags')
+ return this.loggedIn.role === 'admin' ||
+ privileges.includes('users_manage_activation_state') ||
+ privileges.includes('users_delete') ||
+ privileges.includes('users_manage_tags')
},
hasNote () {
return this.relationship.note
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index 751bfd5a0..49d6fd60a 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -81,7 +81,7 @@ const UserProfile = {
return this.isUs || !this.user.hide_followers
},
favoritesTabVisible () {
- return this.isUs || !this.user.hide_favorites
+ return this.isUs || (this.$store.state.instance.pleromaPublicFavouritesAvailable && !this.user.hide_favorites)
},
formattedBirthday () {
const browserLocale = localeService.internalToBrowserLocale(this.$i18n.locale)
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 019beba1c..14f36844b 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -117,6 +117,7 @@
"flash_security": "Note that this can be potentially dangerous since Flash content is still arbitrary code.",
"flash_fail": "Failed to load flash content, see console for details.",
"scope_in_timeline": {
+ "local": "Non-federated",
"direct": "Direct",
"private": "Followers-only",
"public": "Public",
@@ -171,6 +172,7 @@
"interactions": "Interactions",
"dms": "Direct messages",
"public_tl": "Public timeline",
+ "bubble": "Bubble timeline",
"timeline": "Timeline",
"home_timeline": "Home timeline",
"twkn": "Known Network",
@@ -289,7 +291,8 @@
"text/plain": "Plain text",
"text/html": "HTML",
"text/markdown": "Markdown",
- "text/bbcode": "BBCode"
+ "text/bbcode": "BBCode",
+ "text/x.misskeymarkdown": "MFM"
},
"content_type_selection": "Post format",
"content_warning": "Subject (optional)",
diff --git a/src/modules/api.js b/src/modules/api.js
index 69c8282b8..ab8d7162f 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -211,6 +211,7 @@ const api = {
statusId = false,
bookmarkFolderId = false
}) {
+ if (timeline === 'favourites' && !store.rootState.instance.pleromaPublicFavouritesAvailable) return
if (store.state.fetchers[timeline]) return
const fetcher = store.state.backendInteractor.startFetchingTimeline({
@@ -281,6 +282,7 @@ const api = {
// Bookmark folders
startFetchingBookmarkFolders (store) {
if (store.state.fetchers.bookmarkFolders) return
+ if (!store.rootState.instance.pleromaBookmarkFoldersAvailable) return
const fetcher = store.state.backendInteractor.startFetchingBookmarkFolders({ store })
store.commit('addFetcher', { fetcherName: 'bookmarkFolders', fetcher })
},
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 83671a881..39d1fc662 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -143,7 +143,7 @@ const defaultState = {
emoji: {},
emojiFetched: false,
unicodeEmojiAnnotations: {},
- pleromaBackend: true,
+ pleromaExtensionsAvailable: true,
postFormats: [],
restrictedNicknames: [],
safeDM: true,
@@ -156,12 +156,14 @@ const defaultState = {
pleromaChatMessagesAvailable: false,
pleromaCustomEmojiReactionsAvailable: false,
pleromaBookmarkFoldersAvailable: false,
+ pleromaPublicFavouritesAvailable: true,
gopherAvailable: false,
mediaProxyAvailable: false,
suggestionsEnabled: false,
suggestionsWeb: '',
quotingAvailable: false,
groupActorAvailable: false,
+ localBubbleInstances: [], // Akkoma
// Html stuff
instanceSpecificPanelContent: '',
@@ -340,7 +342,10 @@ const instance = {
async getCustomEmoji ({ commit, state }) {
try {
- const res = await window.fetch('/api/pleroma/emoji.json')
+ let res = await window.fetch('/api/v1/pleroma/emoji')
+ if (!res.ok) {
+ 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
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index d08b3334c..efdfc5894 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -39,6 +39,7 @@ export const defaultState = () => ({
conversationsObject: {},
maxId: 0,
favorites: new Set(),
+ pleromaScrobblesAvailable: true, // not reported in nodeinfo
timelines: {
mentions: emptyTl(),
public: emptyTl(),
@@ -50,7 +51,8 @@ export const defaultState = () => ({
tag: emptyTl(),
dms: emptyTl(),
bookmarks: emptyTl(),
- list: emptyTl()
+ list: emptyTl(),
+ bubble: emptyTl()
}
})
@@ -108,12 +110,21 @@ const sortTimeline = (timeline) => {
}
const getLatestScrobble = (state, user) => {
+ const scrobbles = state.pleromaScrobblesAvailable
+ if (!scrobbles) return
+
if (state.scrobblesNextFetch[user.id] && state.scrobblesNextFetch[user.id] > Date.now()) {
return
}
state.scrobblesNextFetch[user.id] = Date.now() + 24 * 60 * 60 * 1000
+ if (!scrobbles) return
apiService.fetchScrobbles({ accountId: user.id }).then((scrobbles) => {
+ if (scrobbles?.error?.status === 501) {
+ state.pleromaScrobblesAvailable = false
+ return
+ }
+
if (scrobbles.length > 0) {
user.latestScrobble = scrobbles[0]
diff --git a/src/modules/users.js b/src/modules/users.js
index 01936c716..c59c04dff 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -599,6 +599,7 @@ const users = {
return new Promise((resolve, reject) => {
const commit = store.commit
const dispatch = store.dispatch
+ const rootState = store.rootState
commit('beginLogin')
store.rootState.api.backendInteractor.verifyCredentials(accessToken)
.then((data) => {
@@ -665,8 +666,10 @@ const users = {
// Start fetching notifications
dispatch('startFetchingNotifications')
- // Start fetching chats
- dispatch('startFetchingChats')
+ if (rootState.instance.pleromaChatMessagesAvailable) {
+ // Start fetching chats
+ dispatch('startFetchingChats')
+ }
}
dispatch('startFetchingLists')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 117c621d9..6de94278e 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -15,7 +15,7 @@ const TAG_USER_URL = '/api/pleroma/admin/users/tag'
const PERMISSION_GROUP_URL = (screenName, right) => `/api/pleroma/admin/users/${screenName}/permission_group/${right}`
const ACTIVATE_USER_URL = '/api/pleroma/admin/users/activate'
const DEACTIVATE_USER_URL = '/api/pleroma/admin/users/deactivate'
-const ADMIN_USERS_URL = '/api/pleroma/admin/users'
+const ADMIN_USERS_URL = '/api/v1/pleroma/admin/users'
const SUGGESTIONS_URL = '/api/v1/suggestions'
const NOTIFICATION_SETTINGS_URL = '/api/pleroma/notification_settings'
const NOTIFICATION_READ_URL = '/api/v1/pleroma/notifications/read'
@@ -61,6 +61,7 @@ const MASTODON_LIST_TIMELINE_URL = id => `/api/v1/timelines/list/${id}`
const MASTODON_LIST_ACCOUNTS_URL = id => `/api/v1/lists/${id}/accounts`
const MASTODON_TAG_TIMELINE_URL = tag => `/api/v1/timelines/tag/${tag}`
const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks'
+const AKKOMA_BUBBLE_TIMELINE_URL = '/api/v1/timelines/bubble'
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`
@@ -99,7 +100,7 @@ const PLEROMA_CHAT_URL = id => `/api/v1/pleroma/chats/by-account-id/${id}`
const PLEROMA_CHAT_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read`
const PLEROMA_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => `/api/v1/pleroma/chats/${chatId}/messages/${messageId}`
-const PLEROMA_ADMIN_REPORTS = '/api/pleroma/admin/reports'
+const PLEROMA_ADMIN_REPORTS = '/api/v1/pleroma/admin/reports'
const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups'
const PLEROMA_ANNOUNCEMENTS_URL = '/api/v1/pleroma/admin/announcements'
const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements'
@@ -111,10 +112,10 @@ const PLEROMA_USER_FAVORITES_TIMELINE_URL = id => `/api/v1/pleroma/accounts/${id
const PLEROMA_BOOKMARK_FOLDERS_URL = '/api/v1/pleroma/bookmark_folders'
const PLEROMA_BOOKMARK_FOLDER_URL = id => `/api/v1/pleroma/bookmark_folders/${id}`
-const PLEROMA_ADMIN_CONFIG_URL = '/api/pleroma/admin/config'
-const PLEROMA_ADMIN_DESCRIPTIONS_URL = '/api/pleroma/admin/config/descriptions'
-const PLEROMA_ADMIN_FRONTENDS_URL = '/api/pleroma/admin/frontends'
-const PLEROMA_ADMIN_FRONTENDS_INSTALL_URL = '/api/pleroma/admin/frontends/install'
+const PLEROMA_ADMIN_CONFIG_URL = '/api/v1/pleroma/admin/config'
+const PLEROMA_ADMIN_DESCRIPTIONS_URL = '/api/v1/pleroma/admin/config/descriptions'
+const PLEROMA_ADMIN_FRONTENDS_URL = '/api/v1/pleroma/admin/frontends'
+const PLEROMA_ADMIN_FRONTENDS_INSTALL_URL = '/api/v1/pleroma/admin/frontends/install'
const PLEROMA_EMOJI_RELOAD_URL = '/api/pleroma/admin/reload_emoji'
const PLEROMA_EMOJI_IMPORT_FS_URL = '/api/pleroma/emoji/packs/import'
@@ -707,7 +708,8 @@ const fetchTimeline = ({
publicFavorites: PLEROMA_USER_FAVORITES_TIMELINE_URL,
tag: MASTODON_TAG_TIMELINE_URL,
bookmarks: MASTODON_BOOKMARK_TIMELINE_URL,
- quotes: PLEROMA_STATUS_QUOTES_URL
+ quotes: PLEROMA_STATUS_QUOTES_URL,
+ bubble: AKKOMA_BUBBLE_TIMELINE_URL
}
const isNotifications = timeline === 'notifications'
const params = []
diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index d9e3d427a..61eb5313f 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -91,6 +91,8 @@ export const parseUser = (data) => {
output.bot = data.bot
+ output.privileges = []
+
if (data.pleroma) {
if (data.pleroma.settings_store) {
output.storage = data.pleroma.settings_store['pleroma-fe']
@@ -317,20 +319,18 @@ export const parseStatus = (data) => {
output.edited_at = data.edited_at
+ const { pleroma } = data
+
if (data.pleroma) {
- const { pleroma } = data
output.text = pleroma.content ? data.pleroma.content['text/plain'] : data.content
output.summary = pleroma.spoiler_text ? data.pleroma.spoiler_text['text/plain'] : data.spoiler_text
output.statusnet_conversation_id = data.pleroma.conversation_id
output.is_local = pleroma.local
- output.in_reply_to_screen_name = data.pleroma.in_reply_to_account_acct
+ output.in_reply_to_screen_name = 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
- output.quote = pleroma.quote ? parseStatus(pleroma.quote) : undefined
- output.quote_id = pleroma.quote_id ? pleroma.quote_id : (output.quote ? output.quote.id : undefined)
- output.quote_url = pleroma.quote_url
- output.quote_visible = pleroma.quote_visible
+ output.quote_visible = pleroma.quote_visible || true
output.quotes_count = pleroma.quotes_count
output.bookmark_folder_id = pleroma.bookmark_folder
} else {
@@ -338,6 +338,12 @@ export const parseStatus = (data) => {
output.summary = data.spoiler_text
}
+ const quoteRaw = pleroma?.quote || data.quote
+ const quoteData = quoteRaw ? parseStatus(quoteRaw) : undefined
+ output.quote = quoteData
+ output.quote_id = data.quote?.id ?? data.quote_id ?? quoteData?.id ?? pleroma.quote_id
+ output.quote_url = data.quote?.url ?? quoteData?.url ?? pleroma.quote_url
+
output.in_reply_to_status_id = data.in_reply_to_id
output.in_reply_to_user_id = data.in_reply_to_account_id
output.replies_count = data.replies_count
diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js
index d85fc7305..f64646593 100644
--- a/src/services/timeline_fetcher/timeline_fetcher.service.js
+++ b/src/services/timeline_fetcher/timeline_fetcher.service.js
@@ -54,7 +54,7 @@ const fetchAndUpdate = ({
args.bookmarkFolderId = bookmarkFolderId
args.tag = tag
args.withMuted = !hideMutedPosts
- if (loggedIn && ['friends', 'public', 'publicAndExternal'].includes(timeline)) {
+ if (loggedIn && ['friends', 'public', 'publicAndExternal', 'bubble'].includes(timeline)) {
args.replyVisibility = replyVisibility
}
@@ -63,6 +63,10 @@ const fetchAndUpdate = ({
return apiService.fetchTimeline(args)
.then(response => {
if (response.errors) {
+ if (timeline === 'favorites') {
+ rootState.instance.pleromaPublicFavouritesAvailable = false
+ return
+ }
throw new Error(`${response.status} ${response.statusText}`)
}