Compare commits

..

No commits in common. "2e47ce09426852094e3ea63ae1234f0bd0d11067" and "714591e63cce044e36c31eb7ce637bd500b844b2" have entirely different histories.

76 changed files with 2706 additions and 2739 deletions

View file

@ -19,6 +19,7 @@ import {
config.autoAddCss = false
import App from '../App.vue'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import FaviconService from '../services/favicon_service/favicon_service.js'
import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
@ -37,7 +38,7 @@ import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.j
import { useInterfaceStore } from 'src/stores/interface.js'
import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useOAuthStore } from 'src/stores/oauth'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js'
@ -260,6 +261,16 @@ const getStickers = async ({ store }) => {
}
}
const getAppSecret = async ({ store }) => {
const oauth = useOAuthStore()
if (oauth.userToken) {
store.commit(
'setBackendInteractor',
backendInteractorService(oauth.getToken),
)
}
}
const resolveStaffAccounts = ({ store, accounts }) => {
const nicknames = accounts.map((uri) => uri.split('/').pop())
useInstanceStore().set({
@ -450,13 +461,14 @@ const setConfig = async ({ store }) => {
const apiConfig = configInfos[0]
const staticConfig = configInfos[1]
getAppSecret({ store })
await setSettings({ store, apiConfig, staticConfig })
}
const checkOAuthToken = async ({ store }) => {
const oauth = useOAuthStore()
if (oauth.userToken) {
return store.dispatch('loginUser', oauth.userToken)
if (oauth.getUserToken) {
return store.dispatch('loginUser', oauth.getUserToken)
}
return Promise.resolve()
}

View file

@ -35,7 +35,7 @@ const AnnouncementsPage = {
canPostAnnouncement() {
return (
this.currentUser &&
this.currentUser.privileges.has(
this.currentUser.privileges.includes(
'announcements_manage_announcements',
)
)

View file

@ -0,0 +1,15 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEllipsisH } from '@fortawesome/free-solid-svg-icons'
library.add(faEllipsisH)
const BookmarkFolderCard = {
props: ['folder', 'allBookmarks'],
computed: {
firstLetter() {
return this.folder ? this.folder.name[0] : null
},
},
}
export default BookmarkFolderCard

View file

@ -0,0 +1,111 @@
<template>
<div
v-if="allBookmarks"
class="bookmark-folder-card"
>
<router-link
:to="{ name: 'bookmarks' }"
class="bookmark-folder-name"
>
<span class="icon">
<FAIcon
fixed-width
class="fa-scale-110 menu-icon"
icon="bookmark"
/>
</span>{{ $t('nav.all_bookmarks') }}
</router-link>
</div>
<div
v-else
class="bookmark-folder-card"
>
<router-link
:to="{ name: 'bookmark-folder', params: { id: folder.id } }"
class="bookmark-folder-name"
>
<img
v-if="folder.emoji_url"
class="iconEmoji iconEmoji-image"
:src="folder.emoji_url"
:alt="folder.emoji"
:title="folder.emoji"
>
<span
v-else-if="folder.emoji"
class="iconEmoji"
>
<span>
{{ folder.emoji }}
</span>
</span>
<span
v-else-if="firstLetter"
class="icon iconLetter fa-scale-110"
>{{ firstLetter }}</span>{{ folder.name }}
</router-link>
<router-link
:to="{ name: 'bookmark-folder-edit', params: { id: folder.id } }"
class="button-folder-edit"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="ellipsis-h"
/>
</router-link>
</div>
</template>
<script src="./bookmark_folder_card.js"></script>
<style lang="scss">
.bookmark-folder-card {
display: flex;
align-items: center;
}
a.bookmark-folder-name {
display: flex;
align-items: center;
flex-grow: 1;
.icon,
.iconLetter,
.iconEmoji {
display: inline-block;
height: 2.5rem;
width: 2.5rem;
margin-right: 0.5rem;
}
.icon,
.iconLetter {
font-size: 1.5rem;
line-height: 2.5rem;
text-align: center;
}
.iconEmoji {
text-align: center;
object-fit: contain;
vertical-align: middle;
> span {
font-size: 1.5rem;
line-height: 2.5rem;
}
}
img.iconEmoji {
padding: 0.25em;
box-sizing: border-box;
}
}
.bookmark-folder-name,
.button-folder-edit {
margin: 0;
padding: 1em;
color: var(--link);
}
</style>

View file

@ -1,10 +1,8 @@
import EmojiPicker from 'src/components/emoji_picker/emoji_picker.vue'
import apiService from '../../services/api/api.service'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { fetchBookmarkFolders } from 'src/services/api/api.service.js'
const BookmarkFolderEdit = {
data() {
@ -24,10 +22,8 @@ const BookmarkFolderEdit = {
},
created() {
if (!this.id) return
fetchBookmarkFolders({
credentials: useOAuthStore().token,
}).then((folders) => {
const credentials = this.$store.state.users.currentUser.credentials
apiService.fetchBookmarkFolders({ credentials }).then((folders) => {
const folder = folders.find((folder) => folder.id === this.id)
if (!folder) return

View file

@ -1,4 +1,4 @@
import FolderCard from 'src/components/folder_card/folder_card.vue'
import BookmarkFolderCard from 'src/components/bookmark_folder_card/bookmark_folder_card.vue'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
@ -9,7 +9,7 @@ const BookmarkFolders = {
}
},
components: {
FolderCard,
BookmarkFolderCard,
},
computed: {
bookmarkFolders() {

View file

@ -12,28 +12,14 @@
</router-link>
</div>
<div class="panel-body">
<div class="list-item FolderCard">
<router-link
:to="{ name: 'bookmarks' }"
class="folder-name"
>
<span class="icon">
<FAIcon
fixed-width
class="fa-scale-110 menu-icon"
icon="bookmark"
/>
</span>{{ $t('nav.all_bookmarks') }}
</router-link>
</div>
<FolderCard
<BookmarkFolderCard
:all-bookmarks="true"
class="list-item"
/>
<BookmarkFolderCard
v-for="folder in bookmarkFolders.slice().reverse()"
:key="folder"
:name="folder.name"
:emoji="folder.emoji"
:emoji-url="folder.emoji_url"
:link="{ name: 'bookmark-folder', params: { id: folder.id } }"
:link-edit="{ name: 'bookmark-folder-edit', params: { id: folder.id } }"
:folder="folder"
class="list-item"
/>
</div>

View file

@ -17,13 +17,6 @@ import {
} from './chat_layout_utils.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
chatMessages,
getOrCreateChat,
sendChatMessage,
} from 'src/services/api/api.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faChevronDown, faChevronLeft } from '@fortawesome/free-solid-svg-icons'
@ -122,6 +115,7 @@ const Chat = {
mobileLayout: (store) => store.layoutType === 'mobile',
}),
...mapState({
backendInteractor: (state) => state.api.backendInteractor,
mastoUserSocketStatus: (state) => state.api.mastoUserSocketStatus,
currentUser: (state) => state.users.currentUser,
}),
@ -273,46 +267,42 @@ const Chat = {
const fetchOlderMessages = !!maxId
const sinceId = fetchLatest && chatMessageService.maxId
return chatMessages({
id: chatId,
maxId,
sinceId,
credentials: useOAuthStore().token,
}).then((messages) => {
// Clear the current chat in case we're recovering from a ws connection loss.
if (isFirstFetch) {
chatService.clear(chatMessageService)
}
return this.backendInteractor
.chatMessages({ id: chatId, maxId, sinceId })
.then((messages) => {
// Clear the current chat in case we're recovering from a ws connection loss.
if (isFirstFetch) {
chatService.clear(chatMessageService)
}
const positionBeforeUpdate = getScrollPosition()
this.$store
.dispatch('addChatMessages', { chatId, messages })
.then(() => {
this.$nextTick(() => {
if (fetchOlderMessages) {
this.handleScrollUp(positionBeforeUpdate)
}
const positionBeforeUpdate = getScrollPosition()
this.$store
.dispatch('addChatMessages', { chatId, messages })
.then(() => {
this.$nextTick(() => {
if (fetchOlderMessages) {
this.handleScrollUp(positionBeforeUpdate)
}
// In vertical screens, the first batch of fetched messages may not always take the
// full height of the scrollable container.
// If this is the case, we want to fetch the messages until the scrollable container
// is fully populated so that the user has the ability to scroll up and load the history.
if (!isScrollable() && messages.length > 0) {
this.fetchChat({
maxId: this.currentChatMessageService.minId,
})
}
// In vertical screens, the first batch of fetched messages may not always take the
// full height of the scrollable container.
// If this is the case, we want to fetch the messages until the scrollable container
// is fully populated so that the user has the ability to scroll up and load the history.
if (!isScrollable() && messages.length > 0) {
this.fetchChat({
maxId: this.currentChatMessageService.minId,
})
}
})
})
})
})
})
},
async startFetching() {
let chat = this.findOpenedChatByRecipientId(this.recipientId)
if (!chat) {
try {
chat = await getOrCreateChat({
chat = await this.backendInteractor.getOrCreateChat({
accountId: this.recipientId,
credentials: useOAuthStore().token,
})
} catch (e) {
console.error('Error creating or getting a chat', e)
@ -379,10 +369,8 @@ const Chat = {
doSendMessage({ params, fakeMessage, retriesLeft = MAX_RETRIES }) {
if (retriesLeft <= 0) return
sendChatMessage({
params,
credentials: useOAuthStore().token,
})
this.backendInteractor
.sendChatMessage(params)
.then((data) => {
this.$store.dispatch('addChatMessages', {
chatId: this.currentChat.id,

View file

@ -4,7 +4,6 @@
overflow: hidden;
box-sizing: border-box;
cursor: pointer;
width: 100%;
:focus {
outline: none;

View file

@ -3,10 +3,6 @@ import { mapGetters, mapState } from 'vuex'
import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import { useOAuthStore } from 'src/stores/oauth.js'
import { chats } from 'src/services/api/api.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faChevronLeft, faSearch } from '@fortawesome/free-solid-svg-icons'
@ -26,9 +22,7 @@ const chatNew = {
}
},
async created() {
const { chats } = await chats({
credentials: useOAuthStore().token,
})
const { chats } = await this.backendInteractor.chats()
chats.forEach((chat) => this.suggestions.push(chat.account))
},
computed: {
@ -44,6 +38,7 @@ const chatNew = {
},
...mapState({
currentUser: (state) => state.users.currentUser,
backendInteractor: (state) => state.api.backendInteractor,
}),
...mapGetters(['findUser']),
},

View file

@ -9,9 +9,6 @@ import { WSConnectionStatus } from '../../services/api/api.service.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { fetchConversation, fetchStatus } from 'src/services/api/api.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -439,26 +436,22 @@ const conversation = {
methods: {
fetchConversation() {
if (this.status) {
fetchConversation({
id: this.statusId,
credentials: useOAuthStore().token,
}).then(({ ancestors, descendants }) => {
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
this.$store.dispatch('addNewStatuses', { statuses: descendants })
this.setHighlight(this.originalStatusId)
})
this.$store.state.api.backendInteractor
.fetchConversation({ id: this.statusId })
.then(({ ancestors, descendants }) => {
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
this.$store.dispatch('addNewStatuses', { statuses: descendants })
this.setHighlight(this.originalStatusId)
})
} else {
this.loadStatusError = null
fetchStatus({
id: this.statusId,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.fetchStatus({ id: this.statusId })
.then((status) => {
this.$store.dispatch('addNewStatuses', { statuses: [status] })
this.fetchConversation()
})
.catch((error) => {
console.error(error)
this.loadStatusError = error
})
}

View file

@ -1,38 +0,0 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEllipsisH } from '@fortawesome/free-solid-svg-icons'
library.add(faEllipsisH)
const FolderCard = {
props: {
name: {
type: String,
required: true,
},
emoji: {
type: String,
required: false,
default: null,
},
emojiUrl: {
type: String,
required: false,
default: null,
},
link: {
type: Object,
required: true,
},
linkEdit: {
type: Object,
required: true,
},
},
computed: {
firstLetter() {
return this.name[0]
},
},
}
export default FolderCard

View file

@ -1,84 +0,0 @@
<template>
<div class="FolderCard">
<router-link
:to="link"
class="folder-name"
>
<img
v-if="emojiUrl"
class="iconEmoji iconEmoji-image"
:src="emojiUrl"
:alt="emoji"
:title="emoji"
>
<span
v-else-if="emoji"
class="iconEmoji"
>
<span>
{{ emoji }}
</span>
</span>
<span
v-else-if="firstLetter"
class="icon iconLetter fa-scale-110"
>{{ firstLetter }}</span>{{ name }}
</router-link>
<router-link
:to="linkEdit"
class="button-folder-edit"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="ellipsis-h"
/>
</router-link>
</div>
</template>
<script src="./folder_card.js"></script>
<style lang="scss">
.FolderCard {
display: flex;
align-items: center;
.folder-name {
display: flex;
align-items: center;
flex-grow: 1;
.icon,
.iconLetter,
.iconEmoji {
display: inline-block;
height: 2.5rem;
width: 2.5rem;
margin-right: 0.5rem;
}
.icon,
.iconLetter {
font-size: 1.5rem;
line-height: 2.5rem;
text-align: center;
}
.iconEmoji {
text-align: center;
object-fit: contain;
vertical-align: middle;
> span {
font-size: 1.5rem;
line-height: 2.5rem;
}
}
img.iconEmoji {
padding: 0.25em;
box-sizing: border-box;
}
}
}
</style>

View file

@ -4,9 +4,6 @@ import { notificationsFromStore } from '../../services/notification_utils/notifi
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { approveUser, denyUser } from 'src/services/api/api.service.js'
const FollowRequestCard = {
props: ['user'],
@ -51,10 +48,7 @@ const FollowRequestCard = {
}
},
doApprove() {
approveUser({
id: this.user.id,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
this.$store.dispatch('removeFollowRequest', this.user)
const notifId = this.findFollowRequestNotificationId()
@ -76,14 +70,12 @@ const FollowRequestCard = {
},
doDeny() {
const notifId = this.findFollowRequestNotificationId()
denyUser({
id: this.user.id,
credentials: useOAuthStore().token,
}).then(() => {
this.$store.dispatch('dismissNotificationLocal', { id: notifId })
this.$store.dispatch('removeFollowRequest', this.user)
})
this.$store.state.api.backendInteractor
.denyUser({ id: this.user.id })
.then(() => {
this.$store.dispatch('dismissNotificationLocal', { id: notifId })
this.$store.dispatch('removeFollowRequest', this.user)
})
this.hideDenyConfirmDialog()
},
},

View file

@ -33,10 +33,6 @@
&:not(:last-child) {
border-bottom: 1px dotted var(--border);
}
&:empty {
border: none;
}
}
.header {

View file

@ -1,4 +1,4 @@
import FolderCard from 'src/components/folder_card/folder_card.vue'
import ListsCard from 'src/components/lists_card/lists_card.vue'
import { useListsStore } from 'src/stores/lists.js'
@ -9,7 +9,7 @@ const Lists = {
}
},
components: {
FolderCard,
ListsCard,
},
computed: {
lists() {

View file

@ -14,12 +14,10 @@
</router-link>
</div>
<div class="panel-body">
<FolderCard
<ListsCard
v-for="list in lists.slice().reverse()"
:key="list"
:name="list.title"
:link="{ name: 'lists-timeline', params: { id: list.id } }"
:link-edit="{ name: 'lists-edit', params: { id: list.id } }"
:list="list"
class="list-item"
/>
</div>

View file

@ -0,0 +1,10 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEllipsisH } from '@fortawesome/free-solid-svg-icons'
library.add(faEllipsisH)
const ListsCard = {
props: ['list'],
}
export default ListsCard

View file

@ -0,0 +1,38 @@
<template>
<div class="list-card">
<router-link
:to="{ name: 'lists-timeline', params: { id: list.id } }"
class="list-name"
>
{{ list.title }}
</router-link>
<router-link
:to="{ name: 'lists-edit', params: { id: list.id } }"
class="button-list-edit"
>
<FAIcon
class="fa-scale-110 fa-old-padding"
icon="ellipsis-h"
/>
</router-link>
</div>
</template>
<script src="./lists_card.js"></script>
<style lang="scss">
.list-card {
display: flex;
}
.list-name {
flex-grow: 1;
}
.list-name,
.button-list-edit {
margin: 0;
padding: 1em;
color: var(--link);
}
</style>

View file

@ -15,10 +15,8 @@ import {
import { useInstanceStore } from 'src/stores/instance.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js'
import { approveUser, denyUser } from 'src/services/api/api.service.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { library } from '@fortawesome/fontawesome-svg-core'
@ -144,10 +142,7 @@ const Notification = {
}
},
doApprove() {
approveUser({
id: this.user.id,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
this.$store.dispatch('removeFollowRequest', this.user)
this.$store.dispatch('markSingleNotificationAsSeen', {
id: this.notification.id,
@ -168,15 +163,14 @@ const Notification = {
}
},
doDeny() {
denyUser({
id: this.user.id,
credentials: useOAuthStore().token,
}).then(() => {
this.$store.dispatch('dismissNotificationLocal', {
id: this.notification.id,
this.$store.state.api.backendInteractor
.denyUser({ id: this.user.id })
.then(() => {
this.$store.dispatch('dismissNotificationLocal', {
id: this.notification.id,
})
this.$store.dispatch('removeFollowRequest', this.user)
})
this.$store.dispatch('removeFollowRequest', this.user)
})
this.hideDenyConfirmDialog()
},
},

View file

@ -1,7 +1,3 @@
import { useOAuthStore } from 'src/stores/oauth.js'
import { fetchUser } from 'src/services/api/api.service.js'
const RemoteUserResolver = {
data: () => ({
error: false,
@ -11,11 +7,10 @@ const RemoteUserResolver = {
},
methods: {
redirect() {
const id = this.$route.params.username + '@' + this.$route.params.hostname
fetchUser({
id,
credentials: useOAuthStore().token,
})
const acct =
this.$route.params.username + '@' + this.$route.params.hostname
this.$store.state.api.backendInteractor
.fetchUser({ id: acct })
.then((externalUser) => {
if (externalUser.error) {
this.error = true

View file

@ -11,7 +11,6 @@ import ModifiedIndicator from '../helpers/modified_indicator.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
import StringSetting from '../helpers/string_setting.vue'
import { useAdminSettingsStore } from 'src/stores/admin_settings.js'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
@ -99,10 +98,10 @@ const EmojiTab = {
methods: {
reloadEmoji() {
useAdminSettingsStore().reloadEmoji()
this.$store.state.api.backendInteractor.reloadEmoji()
},
importFromFS() {
useAdminSettingsStore().importEmojiFromFS()
this.$store.state.api.backendInteractor.importEmojiFromFS()
},
emojiAddr(name) {
if (this.pack.remote !== undefined) {
@ -114,7 +113,7 @@ const EmojiTab = {
},
createEmojiPack() {
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.createEmojiPack({ name: this.newPackName })
.then((resp) => resp.json())
.then((resp) => {
@ -131,7 +130,7 @@ const EmojiTab = {
})
},
deleteEmojiPack() {
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.deleteEmojiPack({ name: this.packName })
.then((resp) => resp.json())
.then((resp) => {
@ -158,7 +157,7 @@ const EmojiTab = {
return edited !== def
},
savePackMetadata() {
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.saveEmojiPackMetadata({ name: this.packName, newData: this.packMeta })
.then((resp) => resp.json())
.then((resp) => {
@ -183,7 +182,7 @@ const EmojiTab = {
useEmojiStore()
.getAdminPacks(
this.remotePackInstance,
useAdminSettingsStore().listEmojiPacks,
this.$store.state.api.backendInteractor.listEmojiPacks,
)
.then((allPacks) => {
this.knownLocalPacks = allPacks
@ -196,7 +195,7 @@ const EmojiTab = {
useEmojiStore()
.getAdminPacks(
this.remotePackInstance,
useAdminSettingsStore().listRemoteEmojiPacks,
this.$store.state.api.backendInteractor.listRemoteEmojiPacks,
)
.then((allPacks) => {
let inst = this.remotePackInstance
@ -227,7 +226,7 @@ const EmojiTab = {
this.remotePackDownloadAs = this.pack.remote.baseName
}
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.downloadRemoteEmojiPack({
instance: this.pack.remote.instance,
packName: this.pack.remote.baseName,
@ -248,7 +247,7 @@ const EmojiTab = {
})
},
downloadRemoteURLPack() {
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.downloadRemoteEmojiPackZIP({
url: this.remotePackURL,
packName: this.newPackName,
@ -269,7 +268,7 @@ const EmojiTab = {
})
},
downloadRemoteFilePack() {
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.downloadRemoteEmojiPackZIP({
file: this.remotePackFile[0],
packName: this.newPackName,

View file

@ -71,7 +71,7 @@ const FrontendsTab = {
const payload = { name, ref }
this.working = true
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.installFrontend({ payload })
.finally(() => {
this.working = false

View file

@ -1,6 +1,5 @@
.FrontendsTab {
padding: 0 1em;
.cards-list {
padding: 0;
}

View file

@ -133,7 +133,7 @@
<AdminUserCard :user-id="item.id" />
</template>
<template #empty>
<span>{{ $t('admin_dash.users.no_users_found') }}</span>
<span>{{ $t('admin_dash.users.no_users_found')}}</span>
</template>
</List>
</div>

View file

@ -153,14 +153,6 @@ import Popover from 'components/popover/popover.vue'
import SelectComponent from 'components/select/select.vue'
import { defineAsyncComponent } from 'vue'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
addNewEmojiFile,
deleteEmojiFile,
updateEmojiFile,
} from 'src/services/api/admin.js'
export default {
components: {
Popover,
@ -251,14 +243,14 @@ export default {
saveEditedEmoji() {
if (!this.isEdited) return
updateEmojiFile({
packName: this.packName,
shortcode: this.shortcode,
newShortcode: this.editedShortcode,
newFilename: this.editedFile,
force: false,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.updateEmojiFile({
packName: this.packName,
shortcode: this.shortcode,
newShortcode: this.editedShortcode,
newFilename: this.editedFile,
force: false,
})
.then((resp) => {
if (resp.error !== undefined) {
this.$emit('displayError', resp.error)
@ -271,18 +263,18 @@ export default {
},
uploadEmoji() {
let packName = this.remote === undefined ? this.packName : this.copyToPack
addNewEmojiFile({
packName: packName,
file:
this.remote === undefined
? this.uploadURL !== ''
? this.uploadURL
: this.uploadFile[0]
: this.emojiAddr(this.file),
shortcode: this.editedShortcode,
filename: this.editedFile,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.addNewEmojiFile({
packName: packName,
file:
this.remote === undefined
? this.uploadURL !== ''
? this.uploadURL
: this.uploadFile[0]
: this.emojiAddr(this.file),
shortcode: this.editedShortcode,
filename: this.editedFile,
})
.then((resp) => resp.json())
.then((resp) => {
if (resp.error !== undefined) {
@ -305,11 +297,8 @@ export default {
deleteEmoji() {
this.deleteModalVisible = false
deleteEmojiFile({
packName: this.packName,
shortcode: this.shortcode,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.deleteEmojiFile({ packName: this.packName, shortcode: this.shortcode })
.then((resp) => resp.json())
.then((resp) => {
if (resp.error !== undefined) {

View file

@ -12,9 +12,7 @@ import Preview from './old_theme_tab/theme_preview.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { normalizeThemeData, useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { updateProfileImages } from 'src/services/api/api.service.js'
import { newImporter } from 'src/services/export_import/export_import.js'
import {
adoptStyleSheets,
@ -486,10 +484,8 @@ const AppearanceTab = {
}
this.backgroundUploading = true
updateProfileImages({
background,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.updateProfileImages({ background })
.then((data) => {
this.$store.commit('addNewUsers', [data])
this.$store.commit('setCurrentUser', data)

View file

@ -14,10 +14,8 @@ import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { updateProfile } from 'src/services/api/api.service.js'
import localeService from 'src/services/locale/locale.service.js'
import { cacheKey, clearCache, emojiCacheKey } from 'src/services/sw/sw.js'
@ -166,13 +164,12 @@ const ComposingTab = {
),
}
updateProfile({
params,
credentials: useOAuthStore().token,
}).then((user) => {
this.$store.commit('addNewUsers', [user])
this.$store.commit('setCurrentUser', user)
})
this.$store.state.api.backendInteractor
.updateProfile({ params })
.then((user) => {
this.$store.commit('addNewUsers', [user])
this.$store.commit('setCurrentUser', user)
})
},
updateFont(key, value) {
useSyncConfigStore().setSimplePrefAndSave({

View file

@ -4,20 +4,8 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
import Exporter from 'src/components/exporter/exporter.vue'
import Importer from 'src/components/importer/importer.vue'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens.js'
import {
addBackup,
exportFriends,
fetchBlocks,
fetchMutes,
importBlocks,
importFollows,
importMutes,
listBackups,
} from 'src/services/api/api.service.js'
const DataImportExportTab = {
data() {
return {
@ -40,51 +28,42 @@ const DataImportExportTab = {
},
computed: {
...mapState({
backendInteractor: (state) => state.api.backendInteractor,
user: (state) => state.users.currentUser,
}),
},
methods: {
getFollowsContent() {
return exportFriends({
id: this.user.id,
credentials: useOAuthStore().token,
}).then(this.generateExportableUsersContent)
return this.backendInteractor
.exportFriends({ id: this.user.id })
.then(this.generateExportableUsersContent)
},
getBlocksContent() {
return fetchBlocks({
credentials: useOAuthStore().token,
}).then(this.generateExportableUsersContent)
return this.backendInteractor
.fetchBlocks()
.then(this.generateExportableUsersContent)
},
getMutesContent() {
return fetchMutes({
credentials: useOAuthStore().token,
}).then(this.generateExportableUsersContent)
return this.backendInteractor
.fetchMutes()
.then(this.generateExportableUsersContent)
},
importFollows(file) {
return importFollows({
file,
credentials: useOAuthStore().token,
}).then((status) => {
return this.backendInteractor.importFollows({ file }).then((status) => {
if (!status) {
throw new Error('failed')
}
})
},
importBlocks(file) {
return importBlocks({
file,
credentials: useOAuthStore().token,
}).then((status) => {
return this.backendInteractor.importBlocks({ file }).then((status) => {
if (!status) {
throw new Error('failed')
}
})
},
importMutes(file) {
return importMutes({
file,
credentials: useOAuthStore().token,
}).then((status) => {
return this.backendInteractor.importMutes({ file }).then((status) => {
if (!status) {
throw new Error('failed')
}
@ -104,9 +83,8 @@ const DataImportExportTab = {
.join('\n')
},
addBackup() {
addBackup({
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.addBackup()
.then(() => {
this.addedBackup = true
this.addBackupError = false
@ -118,9 +96,8 @@ const DataImportExportTab = {
.then(() => this.fetchBackups())
},
fetchBackups() {
listBackups({
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.listBackups()
.then((res) => {
this.backups = res
this.listBackupsError = false

View file

@ -12,10 +12,8 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { updateProfile } from 'src/services/api/api.service.js'
import localeService from 'src/services/locale/locale.service.js'
const GeneralTab = {
@ -60,13 +58,12 @@ const GeneralTab = {
),
}
updateProfile({
params,
credentials: useOAuthStore().token,
}).then((user) => {
this.$store.commit('addNewUsers', [user])
this.$store.commit('setCurrentUser', user)
})
this.$store.state.api.backendInteractor
.updateProfile({ params })
.then((user) => {
this.$store.commit('addNewUsers', [user])
this.$store.commit('setCurrentUser', user)
})
},
updateFont(path, value) {
useLocalConfigStore().set({ path, value })

View file

@ -10,11 +10,8 @@ import ProgressButton from 'src/components/progress_button/progress_button.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import { useInstanceStore } from 'src/stores/instance.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens.js'
import { importBlocks, importFollows } from 'src/services/api/api.service.js'
const MutesAndBlocks = {
data() {
return {
@ -57,24 +54,22 @@ const MutesAndBlocks = {
return () => this.$store.dispatch('fetch' + group, this.userId)
},
importFollows(file) {
return importFollows({
file,
credentials: useOAuthStore().token,
}).then((status) => {
if (!status) {
throw new Error('failed')
}
})
return this.$store.state.api.backendInteractor
.importFollows({ file })
.then((status) => {
if (!status) {
throw new Error('failed')
}
})
},
importBlocks(file) {
return importBlocks({
file,
credentials: useOAuthStore().token,
}).then((status) => {
if (!status) {
throw new Error('failed')
}
})
return this.$store.state.api.backendInteractor
.importBlocks({ file })
.then((status) => {
if (!status) {
throw new Error('failed')
}
})
},
generateExportableUsersContent(users) {
// Get addresses

View file

@ -1,10 +1,6 @@
import BooleanSetting from '../helpers/boolean_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { updateNotificationSettings } from 'src/services/api/api.service.js'
const NotificationsTab = {
data() {
return {
@ -31,8 +27,7 @@ const NotificationsTab = {
},
methods: {
updateNotificationSettings() {
updateNotificationSettings({
credentials: useOAuthStore().token,
this.$store.state.api.backendInteractor.updateNotificationSettings({
settings: this.notificationSettings,
})
},

View file

@ -3,10 +3,6 @@ import UserCard from 'src/components/user_card/user_card.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { updateProfile } from 'src/services/api/api.service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faCircleNotch,
@ -39,10 +35,9 @@ const ProfileTab = {
const params = {
locked: this.locked,
}
updateProfile({
params,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.updateProfile({ params })
.then((user) => {
this.$store.commit('addNewUsers', [user])
this.$store.commit('setCurrentUser', user)

View file

@ -5,15 +5,6 @@ import Confirm from './confirm.vue'
import RecoveryCodes from './mfa_backup_codes.vue'
import TOTP from './mfa_totp.vue'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
generateMfaBackupCodes,
mfaConfirmOTP,
mfaSetupOTP,
settingsMFA,
} from 'src/services/api/api.service.js'
const Mfa = {
data: () => ({
settings: {
@ -80,6 +71,9 @@ const Mfa = {
confirmNewBackupCodes() {
return this.backupCodes.getNewCodes
},
...mapState({
backendInteractor: (state) => state.api.backendInteractor,
}),
},
methods: {
@ -93,9 +87,7 @@ const Mfa = {
this.backupCodes.inProgress = true
this.backupCodes.codes = []
return generateMfaBackupCodes({
credentials: useOAuthStore().token,
}).then((res) => {
return this.backendInteractor.generateMfaBackupCodes().then((res) => {
this.backupCodes.codes = res.codes
this.backupCodes.inProgress = false
})
@ -120,9 +112,7 @@ const Mfa = {
// prepare setup OTP
this.setupState.state = 'setupOTP'
this.setupState.setupOTPState = 'prepare'
mfaSetupOTP({
credentials: useOAuthStore().token,
}).then((res) => {
this.backendInteractor.mfaSetupOTP().then((res) => {
this.otpSettings = res
this.setupState.setupOTPState = 'confirm'
})
@ -130,17 +120,18 @@ const Mfa = {
doConfirmOTP() {
// handler confirm enable OTP
this.error = null
mfaConfirmOTP({
token: this.otpConfirmToken,
password: this.currentPassword,
credentials: useOAuthStore().token,
}).then((res) => {
if (res.error) {
this.error = res.error
return
}
this.completeSetup()
})
this.backendInteractor
.mfaConfirmOTP({
token: this.otpConfirmToken,
password: this.currentPassword,
})
.then((res) => {
if (res.error) {
this.error = res.error
return
}
this.completeSetup()
})
},
completeSetup() {
@ -161,9 +152,7 @@ const Mfa = {
// fetch settings from server
async fetchSettings() {
const result = await settingsMFA({
credentials: useOAuthStore().token,
})
const result = await this.backendInteractor.settingsMFA()
if (result.error) return
this.settings = result.settings
this.settings.available = true

View file

@ -2,10 +2,6 @@ import { mapState } from 'vuex'
import Confirm from './confirm.vue'
import { useOAuthStore } from 'src/stores/oauth.js'
import { mfaDisableOTP } from 'src/services/api/api.service.js'
export default {
props: ['settings'],
data: () => ({
@ -21,6 +17,9 @@ export default {
isActivated() {
return this.settings.totp
},
...mapState({
backendInteractor: (state) => state.api.backendInteractor,
}),
},
methods: {
doActivate() {
@ -37,18 +36,19 @@ export default {
// confirm deactivate TOTP method
this.error = null
this.inProgress = true
mfaDisableOTP({
password: this.currentPassword,
credentials: useOAuthStore().token,
}).then((res) => {
this.inProgress = false
if (res.error) {
this.error = res.error
return
}
this.deactivate = false
this.$emit('deactivate')
})
this.backendInteractor
.mfaDisableOTP({
password: this.currentPassword,
})
.then((res) => {
this.inProgress = false
if (res.error) {
this.error = res.error
return
}
this.deactivate = false
this.$emit('deactivate')
})
},
},
}

View file

@ -4,18 +4,8 @@ import Mfa from './mfa.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens'
import {
addAlias,
changeEmail,
changePassword,
deleteAccount,
deleteAlias,
listAliases,
moveAccount,
} from 'src/services/api/api.service.js'
import localeService from 'src/services/locale/locale.service.js'
const SecurityTab = {
@ -75,79 +65,78 @@ const SecurityTab = {
this.deletingAccount = true
},
deleteAccount() {
deleteAccount({
credentials: useOAuthStore().token,
password: this.deleteAccountConfirmPasswordInput,
}).then((res) => {
if (res.status === 'success') {
this.$store.dispatch('logout')
this.$router.push({ name: 'root' })
} else {
this.deleteAccountError = res.error
}
})
this.$store.state.api.backendInteractor
.deleteAccount({ password: this.deleteAccountConfirmPasswordInput })
.then((res) => {
if (res.status === 'success') {
this.$store.dispatch('logout')
this.$router.push({ name: 'root' })
} else {
this.deleteAccountError = res.error
}
})
},
changePassword() {
const params = {
password: this.changePasswordInputs[0],
newPassword: this.changePasswordInputs[1],
newPasswordConfirmation: this.changePasswordInputs[2],
credentials: useOAuthStore().token,
}
changePassword(params).then((res) => {
if (res.status === 'success') {
this.changedPassword = true
this.changePasswordError = false
this.logout()
} else {
this.changedPassword = false
this.changePasswordError = res.error
}
})
this.$store.state.api.backendInteractor
.changePassword(params)
.then((res) => {
if (res.status === 'success') {
this.changedPassword = true
this.changePasswordError = false
this.logout()
} else {
this.changedPassword = false
this.changePasswordError = res.error
}
})
},
changeEmail() {
const params = {
email: this.newEmail,
password: this.changeEmailPassword,
credentials: useOAuthStore().token,
}
changeEmail(params).then((res) => {
if (res.status === 'success') {
this.changedEmail = true
this.changeEmailError = false
} else {
this.changedEmail = false
this.changeEmailError = res.error
}
})
this.$store.state.api.backendInteractor
.changeEmail(params)
.then((res) => {
if (res.status === 'success') {
this.changedEmail = true
this.changeEmailError = false
} else {
this.changedEmail = false
this.changeEmailError = res.error
}
})
},
moveAccount() {
const params = {
targetAccount: this.moveAccountTarget,
password: this.moveAccountPassword,
credentials: useOAuthStore().token,
}
moveAccount(params).then((res) => {
if (res.status === 'success') {
this.movedAccount = true
this.moveAccountError = false
} else {
this.movedAccount = false
this.moveAccountError = res.error
}
})
this.$store.state.api.backendInteractor
.moveAccount(params)
.then((res) => {
if (res.status === 'success') {
this.movedAccount = true
this.moveAccountError = false
} else {
this.movedAccount = false
this.moveAccountError = res.error
}
})
},
removeAlias(alias) {
deleteAlias({
alias,
credentials: useOAuthStore().token,
}).then(() => this.fetchAliases())
this.$store.state.api.backendInteractor
.deleteAlias({ alias })
.then(() => this.fetchAliases())
},
addAlias() {
addAlias({
alias: this.addAliasTarget,
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.addAlias({ alias: this.addAliasTarget })
.then(() => {
this.addedAlias = true
this.addAliasError = false
@ -160,9 +149,8 @@ const SecurityTab = {
.then(() => this.fetchAliases())
},
fetchAliases() {
listAliases({
credentials: useOAuthStore().token,
})
this.$store.state.api.backendInteractor
.listAliases()
.then((res) => {
this.aliases = res.aliases
this.listAliasesError = false

View file

@ -131,41 +131,40 @@ const Status = {
Quote: defineAsyncComponent(() => import('src/components/quote/quote.vue')),
StatusActionButtons,
},
props: {
statusoid: Object,
replies: Array,
props: [
'statusoid',
'replies',
expandable: Boolean,
focused: Boolean,
highlight: Boolean,
compact: Boolean,
isPreview: Boolean,
noHeading: Boolean,
inlineExpanded: Boolean,
showPinned: Boolean,
inProfile: Boolean,
inConversation: Boolean,
inQuote: Boolean,
'expandable',
'focused',
'highlight',
'compact',
'isPreview',
'noHeading',
'inlineExpanded',
'showPinned',
'inProfile',
'inConversation',
'inQuote',
'profileUserId',
'simpleTree',
'showOtherRepliesAsButton',
'dive',
'ignoreMute',
profileUserId: String,
simpleTree: Boolean,
showOtherRepliesAsButton: Boolean,
dive: Function,
ignoreMute: Boolean,
controlledThreadDisplayStatus: String,
controlledToggleThreadDisplay: Function,
controlledShowingTall: Boolean,
controlledToggleShowingTall: Function,
controlledExpandingSubject: Boolean,
controlledToggleExpandingSubject: Function,
controlledShowingLongSubject: Boolean,
controlledToggleShowingLongSubject: Function,
controlledReplying: Boolean,
controlledToggleReplying: Function,
controlledMediaPlaying: Boolean,
controlledSetMediaPlaying: Function,
},
'controlledThreadDisplayStatus',
'controlledToggleThreadDisplay',
'controlledShowingTall',
'controlledToggleShowingTall',
'controlledExpandingSubject',
'controlledToggleExpandingSubject',
'controlledShowingLongSubject',
'controlledToggleShowingLongSubject',
'controlledReplying',
'controlledToggleReplying',
'controlledMediaPlaying',
'controlledSetMediaPlaying',
],
emits: ['goto', 'toggleExpanded'],
data() {
return {

View file

@ -107,7 +107,7 @@ const StatusActionButtons = {
button
.action?.(this.funcArg)
.then(() => this.$emit('onSuccess'))
.catch((err) => this.$emit('onError', err))
.catch((err) => this.$emit('onError', err.error.error))
},
onExtraClose() {
this.showPin = false

View file

@ -2,7 +2,6 @@ import Popover from 'components/popover/popover.vue'
import SelectComponent from 'components/select/select.vue'
import { mapState } from 'pinia'
import { useAdminSettingsStore } from 'src/stores/admin_settings'
import { useEmojiStore } from 'src/stores/emoji'
import { useInterfaceStore } from 'src/stores/interface'
@ -38,7 +37,7 @@ export default {
})
},
copyToLocalPack() {
useAdminSettingsStore()
this.$store.state.api.backendInteractor
.addNewEmojiFile({
packName: this.packName,
file: this.$attrs.src,

View file

@ -56,7 +56,6 @@
.contents {
flex: 1 0 auto;
min-height: 0;
position: relative;
.hidden {
display: none;

View file

@ -22,11 +22,9 @@ import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.j
import { useInterfaceStore } from 'src/stores/interface'
import { useMediaViewerStore } from 'src/stores/media_viewer'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { usePostStatusStore } from 'src/stores/post_status'
import { useUserHighlightStore } from 'src/stores/user_highlight.js'
import { updateProfile } from 'src/services/api/api.service.js'
import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js'
import localeService from 'src/services/locale/locale.service.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@ -309,9 +307,9 @@ export default {
const privileges = this.loggedIn.privileges
return (
this.loggedIn.role === 'admin' ||
privileges.has('users_manage_activation_state') ||
privileges.has('users_delete') ||
privileges.has('users_manage_tags')
privileges.includes('users_manage_activation_state') ||
privileges.includes('users_delete') ||
privileges.includes('users_manage_tags')
)
},
hasNote() {
@ -599,7 +597,8 @@ export default {
params.header = this.newBannerFile
}
updateProfile({ params })
this.$store.state.api.backendInteractor
.updateProfile({ params })
.then((user) => {
this.newFields.splice(this.newFields.length)
merge(this.newFields, user.fields)

View file

@ -33,7 +33,6 @@
:statusoid="item"
:in-conversation="false"
:focused="false"
ignore-mute
/>
</template>
</List>

View file

@ -5,11 +5,8 @@ import List from 'src/components/list/list.vue'
import Modal from 'src/components/modal/modal.vue'
import UserLink from 'src/components/user_link/user_link.vue'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useReportsStore } from 'src/stores/reports.js'
import { reportUser } from 'src/services/api/api.service.js'
const UserReportingModal = {
components: {
List,
@ -31,7 +28,6 @@ const UserReportingModal = {
return !!this.$store.state.users.currentUser
},
isOpen() {
console.log(this.reportModal)
return this.isLoggedIn && this.reportModal.activated
},
userId() {
@ -74,9 +70,9 @@ const UserReportingModal = {
comment: this.comment,
forward: this.forward,
statusIds: [...this.statusIdsToReport],
credentials: useOAuthStore().token,
}
reportUser({ ...params })
this.$store.state.api.backendInteractor
.reportUser({ ...params })
.then(() => {
this.processing = false
this.resetState()

View file

@ -2,9 +2,6 @@ import FollowCard from 'src/components/follow_card/follow_card.vue'
import apiService from '../../services/api/api.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { fetchUser, suggestions } from 'src/services/api/api.service.js'
const WhoToFollow = {
components: {
@ -20,22 +17,21 @@ const WhoToFollow = {
},
methods: {
showWhoToFollow(reply) {
reply.forEach(({ id }) => {
fetchUser({
id,
credentials: useOAuthStore().token,
}).then((externalUser) => {
if (!externalUser.error) {
this.$store.commit('addNewUsers', [externalUser])
this.users.push(externalUser)
}
})
reply.forEach((i) => {
this.$store.state.api.backendInteractor
.fetchUser({ id: i.acct })
.then((externalUser) => {
if (!externalUser.error) {
this.$store.commit('addNewUsers', [externalUser])
this.users.push(externalUser)
}
})
})
},
getWhoToFollow() {
const credentials = useOAuthStore().token
const credentials = this.$store.state.users.currentUser.credentials
if (credentials) {
suggestions({ credentials }).then((reply) => {
apiService.suggestions({ credentials }).then((reply) => {
this.showWhoToFollow(reply)
})
}

View file

@ -1,10 +1,10 @@
import { shuffle } from 'lodash'
import apiService from '../../services/api/api.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { fetchUser, suggestions } from 'src/services/api/api.service.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
function showWhoToFollow(panel, reply) {
@ -18,15 +18,14 @@ function showWhoToFollow(panel, reply) {
toFollow.img = img
toFollow.name = name
fetchUser({
id: name,
credentials: useOAuthStore().token,
}).then((externalUser) => {
if (!externalUser.error) {
panel.$store.commit('addNewUsers', [externalUser])
toFollow.id = externalUser.id
}
})
panel.$store.state.api.backendInteractor
.fetchUser({ id: name })
.then((externalUser) => {
if (!externalUser.error) {
panel.$store.commit('addNewUsers', [externalUser])
toFollow.id = externalUser.id
}
})
})
}
@ -36,7 +35,7 @@ function getWhoToFollow(panel) {
panel.usersToFollow.forEach((toFollow) => {
toFollow.name = 'Loading...'
})
suggestions({ credentials }).then((reply) => {
apiService.suggestions({ credentials }).then((reply) => {
showWhoToFollow(panel, reply)
})
}

View file

@ -1,28 +1,20 @@
import { Socket } from 'phoenix'
import { WSConnectionStatus } from '../services/api/api.service.js'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useShoutStore } from 'src/stores/shout.js'
import {
fetchTimeline,
getMastodonSocketURI,
ProcessedWS,
} from 'src/services/api/api.service.js'
import followRequestFetcher from 'src/services/follow_request_fetcher/follow_request_fetcher.service'
import notificationsFetcher from 'src/services/notifications_fetcher/notifications_fetcher.service.js'
import timelineFetcher from 'src/services/timeline_fetcher/timeline_fetcher.service.js'
const retryTimeout = (multiplier) => 1000 * multiplier
const api = {
state: {
retryMultiplier: 1,
backendInteractor: backendInteractorService(),
fetchers: {},
socket: null,
mastoUserSocket: null,
@ -33,6 +25,9 @@ const api = {
followRequestCount: (state) => state.followRequests.length,
},
mutations: {
setBackendInteractor(state, backendInteractor) {
state.backendInteractor = backendInteractor
},
addFetcher(state, { fetcherName, fetcher }) {
state.fetchers[fetcherName] = fetcher
},
@ -96,17 +91,9 @@ const api = {
try {
const { state, commit, dispatch, rootState } = store
const timelineData = rootState.statuses.timelines.friends
const serv = useInstanceStore().server.replace('http', 'ws')
const credentials = useOAuthStore().token
const url = getMastodonSocketURI({ credentials }, serv)
state.mastoUserSocket = ProcessedWS({
url,
id: 'Unified',
credentials,
state.mastoUserSocket = state.backendInteractor.startUserSocket({
store,
})
state.mastoUserSocket.addEventListener(
'pleroma:authenticated',
() => {
@ -258,7 +245,7 @@ const api = {
return
if (store.state.fetchers[timeline]) return
const fetcher = timelineFetcher.startFetching({
const fetcher = store.state.backendInteractor.startFetchingTimeline({
timeline,
store,
userId,
@ -266,9 +253,7 @@ const api = {
statusId,
bookmarkFolderId,
tag,
credentials: useOAuthStore().token,
})
store.commit('addFetcher', { fetcherName: timeline, fetcher })
},
stopFetchingTimeline(store, timeline) {
@ -276,22 +261,19 @@ const api = {
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: timeline, fetcher })
},
fetchTimeline(store, { timeline, ...rest }) {
fetchTimeline({
store.state.backendInteractor.fetchTimeline({
store,
timeline,
...rest,
credentials: useOAuthStore().token,
})
},
// Notifications
startFetchingNotifications(store) {
if (store.state.fetchers.notifications) return
const fetcher = notificationsFetcher.startFetching({
const fetcher = store.state.backendInteractor.startFetchingNotifications({
store,
credentials: useOAuthStore().token,
})
store.commit('addFetcher', { fetcherName: 'notifications', fetcher })
},
@ -300,14 +282,19 @@ const api = {
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'notifications', fetcher })
},
fetchNotifications(store, { ...rest }) {
store.state.backendInteractor.fetchNotifications({
store,
...rest,
})
},
// Follow requests
startFetchingFollowRequests(store) {
if (store.state.fetchers.followRequests) return
const fetcher = followRequestFetcher.startFetchingFollowRequests({
store,
credentials: useOAuthStore().token,
})
const fetcher = store.state.backendInteractor.startFetchingFollowRequests(
{ store },
)
store.commit('addFetcher', { fetcherName: 'followRequests', fetcher })
},
@ -316,6 +303,39 @@ const api = {
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'followRequests', fetcher })
},
removeFollowRequest(store, request) {
const requests = store.state.followRequests.filter((it) => it !== request)
store.commit('setFollowRequests', requests)
},
// Lists
startFetchingLists(store) {
if (store.state.fetchers.lists) return
const fetcher = store.state.backendInteractor.startFetchingLists({
store,
})
store.commit('addFetcher', { fetcherName: 'lists', fetcher })
},
stopFetchingLists(store) {
const fetcher = store.state.fetchers.lists
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'lists', fetcher })
},
// Bookmark folders
startFetchingBookmarkFolders(store) {
if (store.state.fetchers.bookmarkFolders) return
if (!useInstanceCapabilitiesStore().pleromaBookmarkFoldersAvailable)
return
const fetcher =
store.state.backendInteractor.startFetchingBookmarkFolders({ store })
store.commit('addFetcher', { fetcherName: 'bookmarkFolders', fetcher })
},
stopFetchingBookmarkFolders(store) {
const fetcher = store.state.fetchers.bookmarkFolders
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'bookmarkFolders', fetcher })
},
// Pleroma websocket
setWsToken(store, token) {

View file

@ -9,14 +9,6 @@ import {
} from '../services/entity_normalizer/entity_normalizer.service.js'
import { promiseInterval } from '../services/promise_interval/promise_interval.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
chats,
deleteChatMessage,
readChat,
} from 'src/services/api/api.service.js'
const emptyChatList = () => ({
data: [],
idStore: {},
@ -44,7 +36,7 @@ const unreadChatCount = (state) => {
return sumBy(state.chatList.data, 'unread')
}
const chatsModule = {
const chats = {
state: { ...defaultState },
getters: {
currentChat: (state) => state.openedChats[state.currentChatId],
@ -59,6 +51,7 @@ const chatsModule = {
// Chat list
startFetchingChats({ dispatch, commit }) {
const fetcher = () => dispatch('fetchChats', { latest: true })
fetcher()
commit('setChatListFetcher', {
fetcher: () => promiseInterval(fetcher, 5000),
})
@ -67,10 +60,8 @@ const chatsModule = {
commit('setChatListFetcher', { fetcher: undefined })
},
fetchChats({ dispatch, rootState }) {
return chats({
credentials: useOAuthStore().token,
}).then(({ chatList }) => {
dispatch('addNewChats', { chats: chatList })
return rootState.api.backendInteractor.chats().then(({ chats }) => {
dispatch('addNewChats', { chats })
return chats
})
},
@ -122,18 +113,11 @@ const chatsModule = {
commit('readChat', { id, lastReadId })
if (isNewMessage) {
readChat({
id,
lastReadId,
credentials: useOAuthStore().token,
})
rootState.api.backendInteractor.readChat({ id, lastReadId })
}
},
deleteChatMessage({ rootState, commit }, value) {
deleteChatMessage({
...value,
credentials: useOAuthStore().token,
})
rootState.api.backendInteractor.deleteChatMessage(value)
commit('deleteChatMessage', { commit, ...value })
},
resetChats({ commit, dispatch }) {
@ -278,4 +262,4 @@ const chatsModule = {
},
}
export default chatsModule
export default chats

View file

@ -1,4 +1,4 @@
import { markNotificationsAsSeen } from '../services/api/api.service.js'
import apiService from '../services/api/api.service.js'
import {
closeAllDesktopNotifications,
closeDesktopNotification,
@ -11,12 +11,9 @@ import {
import { useI18nStore } from 'src/stores/i18n.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useReportsStore } from 'src/stores/reports.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { dismissNotification } from 'src/services/api/api.service.js'
const emptyNotifications = () => ({
desktopNotificationSilence: true,
maxId: 0,
@ -157,32 +154,33 @@ export const notifications = {
},
markNotificationsAsSeen({ rootState, state, commit }) {
commit('markNotificationsAsSeen')
markNotificationsAsSeen({
id: state.maxId,
credentials: rootState.users.currentUser.credentials,
}).then(() => {
closeAllDesktopNotifications(rootState)
})
apiService
.markNotificationsAsSeen({
id: state.maxId,
credentials: rootState.users.currentUser.credentials,
})
.then(() => {
closeAllDesktopNotifications(rootState)
})
},
markSingleNotificationAsSeen({ rootState, commit }, { id }) {
commit('markSingleNotificationAsSeen', { id })
markNotificationsAsSeen({
single: true,
id,
credentials: rootState.users.currentUser.credentials,
}).then(() => {
closeDesktopNotification(rootState, { id })
})
apiService
.markNotificationsAsSeen({
single: true,
id,
credentials: rootState.users.currentUser.credentials,
})
.then(() => {
closeDesktopNotification(rootState, { id })
})
},
dismissNotificationLocal({ commit }, { id }) {
commit('dismissNotification', { id })
},
dismissNotification({ rootState, commit }, { id }) {
commit('dismissNotification', { id })
dismissNotification({
id,
credentials: useOAuthStore().token,
})
rootState.api.backendInteractor.dismissNotification({ id })
},
updateNotification({ commit }, { id, updater }) {
commit('updateNotification', { id, updater })

View file

@ -1,37 +1,28 @@
import { get, set } from 'lodash'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
updateNotificationSettings,
updateProfile,
} from 'src/services/api/api.service.js'
const defaultApi = ({ rootState, commit }, { path, value }) => {
const params = {}
set(params, path, value)
return updateProfile({
params,
credentials: useOAuthStore().token,
}).then((result) => {
commit('addNewUsers', [result])
commit('setCurrentUser', result)
})
return rootState.api.backendInteractor
.updateProfile({ params })
.then((result) => {
commit('addNewUsers', [result])
commit('setCurrentUser', result)
})
}
const notificationsApi = ({ rootState, commit }, { path, value, oldValue }) => {
const settings = {}
set(settings, path, value)
return updateNotificationSettings({
settings,
credentials: useOAuthStore().token,
}).then((result) => {
if (result.status === 'success') {
commit('confirmProfileOption', { name, value })
} else {
commit('confirmProfileOption', { name, value: oldValue })
}
})
return rootState.api.backendInteractor
.updateNotificationSettings({ settings })
.then((result) => {
if (result.status === 'success') {
commit('confirmProfileOption', { name, value })
} else {
commit('confirmProfileOption', { name, value: oldValue })
}
})
}
/**

View file

@ -13,34 +13,10 @@ import {
slice,
} from 'lodash'
import {
bookmarkStatus,
deleteStatus,
favorite,
fetchEmojiReactions,
fetchFavoritedByUsers,
fetchPinnedStatuses,
fetchRebloggedByUsers,
fetchScrobbles,
fetchStatus,
fetchStatusHistory,
fetchStatusSource,
muteConversation,
pinOwnStatus,
reactWithEmoji,
retweet,
search2,
unbookmarkStatus,
unfavorite,
unmuteConversation,
unpinOwnStatus,
unreactWithEmoji,
unretweet,
} from '../services/api/api.service.js'
import apiService from '../services/api/api.service.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
const emptyTl = (userId = 0) => ({
statuses: [],
@ -155,7 +131,8 @@ const getLatestScrobble = (state, user) => {
state.scrobblesNextFetch[user.id] = Date.now() + 24 * 60 * 60 * 1000
if (!scrobblesSupport) return
fetchScrobbles({ accountId: user.id })
apiService
.fetchScrobbles({ accountId: user.id })
.then((scrobbles) => {
if (scrobbles?.error) {
useInstanceCapabilitiesStore().set('pleromaScrobblesAvailable', false)
@ -625,24 +602,25 @@ const statuses = {
})
},
fetchStatus({ rootState, dispatch }, id) {
return fetchStatus({ id }).then((status) =>
dispatch('addNewStatuses', { statuses: [status] }),
)
return rootState.api.backendInteractor
.fetchStatus({ id })
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
},
fetchStatusSource({ rootState }, status) {
return fetchStatusSource({
return apiService.fetchStatusSource({
id: status.id,
credentials: useOAuthStore().token,
credentials: rootState.users.currentUser.credentials,
})
},
fetchStatusHistory(_, status) {
return fetchStatusHistory({ status })
return apiService.fetchStatusHistory({ status })
},
deleteStatus({ rootState, commit }, status) {
deleteStatus({
id: status.id,
credentials: useOAuthStore().token,
})
apiService
.deleteStatus({
id: status.id,
credentials: rootState.users.currentUser.credentials,
})
.then(() => {
commit('setDeleted', { status })
})
@ -665,111 +643,99 @@ const statuses = {
favorite({ rootState, commit }, status) {
// Optimistic favoriting...
commit('setFavorited', { status, value: true })
favorite({
id: status.id,
credentials: useOAuthStore().token,
}).then((status) =>
commit('setFavoritedConfirm', {
status,
user: rootState.users.currentUser,
}),
)
rootState.api.backendInteractor
.favorite({ id: status.id })
.then((status) =>
commit('setFavoritedConfirm', {
status,
user: rootState.users.currentUser,
}),
)
},
unfavorite({ rootState, commit }, status) {
// Optimistic unfavoriting...
commit('setFavorited', { status, value: false })
unfavorite({
id: status.id,
credentials: useOAuthStore().token,
}).then((status) =>
commit('setFavoritedConfirm', {
status,
user: rootState.users.currentUser,
}),
)
rootState.api.backendInteractor
.unfavorite({ id: status.id })
.then((status) =>
commit('setFavoritedConfirm', {
status,
user: rootState.users.currentUser,
}),
)
},
fetchPinnedStatuses({ rootState, dispatch }, userId) {
fetchPinnedStatuses({
id: userId,
credentials: useOAuthStore().token,
}).then((statuses) =>
dispatch('addNewStatuses', {
statuses,
timeline: 'user',
userId,
showImmediately: true,
noIdUpdate: true,
}),
)
rootState.api.backendInteractor
.fetchPinnedStatuses({ id: userId })
.then((statuses) =>
dispatch('addNewStatuses', {
statuses,
timeline: 'user',
userId,
showImmediately: true,
noIdUpdate: true,
}),
)
},
pinStatus({ rootState, dispatch }, statusId) {
return pinOwnStatus({
id: statusId,
credentials: useOAuthStore().token,
}).then((status) => dispatch('addNewStatuses', { statuses: [status] }))
return rootState.api.backendInteractor
.pinOwnStatus({ id: statusId })
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
},
unpinStatus({ rootState, dispatch }, statusId) {
return unpinOwnStatus({
id: statusId,
credentials: useOAuthStore().token,
}).then((status) => dispatch('addNewStatuses', { statuses: [status] }))
return rootState.api.backendInteractor
.unpinOwnStatus({ id: statusId })
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
},
muteConversation({ rootState, commit }, { id: statusId }) {
return muteConversation({
id: statusId,
credentials: useOAuthStore().token,
}).then((status) => commit('setMutedStatus', status))
return rootState.api.backendInteractor
.muteConversation({ id: statusId })
.then((status) => commit('setMutedStatus', status))
},
unmuteConversation({ rootState, commit }, { id: statusId }) {
return unmuteConversation({
id: statusId,
credentials: useOAuthStore().token,
}).then((status) => commit('setMutedStatus', status))
return rootState.api.backendInteractor
.unmuteConversation({ id: statusId })
.then((status) => commit('setMutedStatus', status))
},
retweet({ rootState, commit }, status) {
// Optimistic retweeting...
commit('setRetweeted', { status, value: true })
retweet({
id: status.id,
credentials: useOAuthStore().token,
}).then((status) =>
commit('setRetweetedConfirm', {
status: status.retweeted_status,
user: rootState.users.currentUser,
}),
)
rootState.api.backendInteractor
.retweet({ id: status.id })
.then((status) =>
commit('setRetweetedConfirm', {
status: status.retweeted_status,
user: rootState.users.currentUser,
}),
)
},
unretweet({ rootState, commit }, status) {
// Optimistic unretweeting...
commit('setRetweeted', { status, value: false })
unretweet({
id: status.id,
credentials: useOAuthStore().token,
}).then((status) =>
commit('setRetweetedConfirm', {
status,
user: rootState.users.currentUser,
}),
)
rootState.api.backendInteractor
.unretweet({ id: status.id })
.then((status) =>
commit('setRetweetedConfirm', {
status,
user: rootState.users.currentUser,
}),
)
},
bookmark({ rootState, commit }, status) {
commit('setBookmarked', { status, value: true })
bookmarkStatus({
id: status.id,
folder_id: status.bookmark_folder_id,
credentials: useOAuthStore().token,
}).then((status) => {
commit('setBookmarkedConfirm', { status })
})
rootState.api.backendInteractor
.bookmarkStatus({ id: status.id, folder_id: status.bookmark_folder_id })
.then((status) => {
commit('setBookmarkedConfirm', { status })
})
},
unbookmark({ rootState, commit }, status) {
commit('setBookmarked', { status, value: false })
unbookmarkStatus({
id: status.id,
credentials: useOAuthStore().token,
}).then((status) => {
commit('setBookmarkedConfirm', { status })
})
rootState.api.backendInteractor
.unbookmarkStatus({ id: status.id })
.then((status) => {
commit('setBookmarkedConfirm', { status })
})
},
queueFlush({ commit }, { timeline, id }) {
commit('queueFlush', { timeline, id })
@ -779,14 +745,8 @@ const statuses = {
},
fetchFavsAndRepeats({ rootState, commit }, id) {
Promise.all([
fetchFavoritedByUsers({
id,
credentials: useOAuthStore().token,
}),
fetchRebloggedByUsers({
id,
credentials: useOAuthStore().token,
}),
rootState.api.backendInteractor.fetchFavoritedByUsers({ id }),
rootState.api.backendInteractor.fetchRebloggedByUsers({ id }),
]).then(([favoritedByUsers, rebloggedByUsers]) => {
commit('addFavs', {
id,
@ -805,11 +765,7 @@ const statuses = {
if (!currentUser) return
commit('addOwnReaction', { id, emoji, currentUser })
reactWithEmoji({
id,
emoji,
credentials: useOAuthStore().token,
}).then(() => {
rootState.api.backendInteractor.reactWithEmoji({ id, emoji }).then(() => {
dispatch('fetchEmojiReactionsBy', id)
})
},
@ -818,70 +774,59 @@ const statuses = {
if (!currentUser) return
commit('removeOwnReaction', { id, emoji, currentUser })
unreactWithEmoji({
id,
emoji,
currentUser: rootState.users.currentUser,
}).then(() => {
dispatch('fetchEmojiReactionsBy', id)
})
rootState.api.backendInteractor
.unreactWithEmoji({ id, emoji })
.then(() => {
dispatch('fetchEmojiReactionsBy', id)
})
},
fetchEmojiReactionsBy({ rootState, commit }, id) {
return fetchEmojiReactions({
id,
credentials: useOAuthStore().token,
}).then((emojiReactions) => {
commit('addEmojiReactionsBy', {
id,
emojiReactions,
currentUser: rootState.users.currentUser,
return rootState.api.backendInteractor
.fetchEmojiReactions({ id })
.then((emojiReactions) => {
commit('addEmojiReactionsBy', {
id,
emojiReactions,
currentUser: rootState.users.currentUser,
})
})
})
},
fetchFavs({ rootState, commit }, id) {
fetchFavoritedByUsers({
id,
credentials: useOAuthStore().token,
}).then((favoritedByUsers) =>
commit('addFavs', {
id,
favoritedByUsers,
currentUser: rootState.users.currentUser,
}),
)
rootState.api.backendInteractor
.fetchFavoritedByUsers({ id })
.then((favoritedByUsers) =>
commit('addFavs', {
id,
favoritedByUsers,
currentUser: rootState.users.currentUser,
}),
)
},
fetchRepeats({ rootState, commit }, id) {
fetchRebloggedByUsers({
id,
credentials: useOAuthStore().token,
}).then((rebloggedByUsers) =>
commit('addRepeats', {
id,
rebloggedByUsers,
currentUser: rootState.users.currentUser,
}),
)
rootState.api.backendInteractor
.fetchRebloggedByUsers({ id })
.then((rebloggedByUsers) =>
commit('addRepeats', {
id,
rebloggedByUsers,
currentUser: rootState.users.currentUser,
}),
)
},
search(store, { q, resolve, limit, offset, following, type }) {
return search2({
q,
resolve,
limit,
offset,
following,
type,
credentials: useOAuthStore().token,
}).then((data) => {
store.commit('addNewUsers', data.accounts)
store.commit(
'addNewUsers',
data.statuses.map((s) => s.user).filter((u) => u),
)
data.statuses = store.commit('addNewStatuses', {
statuses: data.statuses,
return store.rootState.api.backendInteractor
.search2({ q, resolve, limit, offset, following, type })
.then((data) => {
store.commit('addNewUsers', data.accounts)
store.commit(
'addNewUsers',
data.statuses.map((s) => s.user).filter((u) => u),
)
data.statuses = store.commit('addNewStatuses', {
statuses: data.statuses,
})
return data
})
return data
})
},
setVirtualHeight({ commit }, { statusId, height }) {
commit('setVirtualHeight', { statusId, height })

View file

@ -9,7 +9,8 @@ import {
uniq,
} from 'lodash'
import { register } from '../services/api/api.service.js'
import apiService from '../services/api/api.service.js'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import oauthApi from '../services/new_api/oauth.js'
import {
registerPushNotifications,
@ -20,34 +21,15 @@ import {
windowWidth,
} from '../services/window_utils/window_utils'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useListsStore } from 'src/stores/lists.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js'
import {
fetchBlocks,
fetchDomainMutes,
fetchFollowers,
fetchFriends,
fetchMutes,
fetchUser,
fetchUserByName,
fetchUserInLists,
fetchUserRelationship,
followUser,
getCaptcha,
muteUser,
searchUsers,
verifyCredentials,
} from 'src/services/api/api.service.js'
// TODO: Unify with mergeOrAdd in statuses.js
export const mergeOrAdd = (arr, obj, item) => {
if (!item) {
@ -90,38 +72,46 @@ const blockUser = (store, args) => {
store.commit('updateUserRelationship', [predictedRelationship])
store.commit('addBlockId', id)
return blockUser({ id, expiresIn }).then((relationship) => {
store.commit('updateUserRelationship', [relationship])
store.commit('addBlockId', id)
return store.rootState.api.backendInteractor
.blockUser({ id, expiresIn })
.then((relationship) => {
store.commit('updateUserRelationship', [relationship])
store.commit('addBlockId', id)
store.commit('removeStatus', { timeline: 'friends', userId: id })
store.commit('removeStatus', { timeline: 'public', userId: id })
store.commit('removeStatus', {
timeline: 'publicAndExternal',
userId: id,
store.commit('removeStatus', { timeline: 'friends', userId: id })
store.commit('removeStatus', { timeline: 'public', userId: id })
store.commit('removeStatus', {
timeline: 'publicAndExternal',
userId: id,
})
})
})
}
const unblockUser = (store, id) => {
return unblockUser({ id }).then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
return store.rootState.api.backendInteractor
.unblockUser({ id })
.then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
}
const removeUserFromFollowers = (store, id) => {
return removeUserFromFollowers({ id }).then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
return store.rootState.api.backendInteractor
.removeUserFromFollowers({ id })
.then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
}
const editUserNote = (store, { id, comment }) => {
return editUserNote({ id, comment }).then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
return store.rootState.api.backendInteractor
.editUserNote({ id, comment })
.then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
}
const localMuteUser = (store, args) => {
const muteUser = (store, args) => {
const id = typeof args === 'object' ? args.id : args
const expiresIn = typeof args === 'object' ? args.expiresIn : 0
@ -129,14 +119,12 @@ const localMuteUser = (store, args) => {
store.commit('updateUserRelationship', [predictedRelationship])
store.commit('addMuteId', id)
return muteUser({
id,
expiresIn,
credentials: useOAuthStore().token,
}).then((relationship) => {
store.commit('updateUserRelationship', [relationship])
store.commit('addMuteId', id)
})
return store.rootState.api.backendInteractor
.muteUser({ id, expiresIn })
.then((relationship) => {
store.commit('updateUserRelationship', [relationship])
store.commit('addMuteId', id)
})
}
const unmuteUser = (store, id) => {
@ -144,43 +132,39 @@ const unmuteUser = (store, id) => {
predictedRelationship.muting = false
store.commit('updateUserRelationship', [predictedRelationship])
return unmuteUser({ id }).then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
return store.rootState.api.backendInteractor
.unmuteUser({ id })
.then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
}
const hideReblogs = (store, userId) => {
return followUser({
id: userId,
reblogs: false,
credentials: useOAuthStore().token,
}).then((relationship) => {
store.commit('updateUserRelationship', [relationship])
})
return store.rootState.api.backendInteractor
.followUser({ id: userId, reblogs: false })
.then((relationship) => {
store.commit('updateUserRelationship', [relationship])
})
}
const showReblogs = (store, userId) => {
return followUser({
id: userId,
reblogs: true,
credentials: useOAuthStore().token,
}).then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
return store.rootState.api.backendInteractor
.followUser({ id: userId, reblogs: true })
.then((relationship) =>
store.commit('updateUserRelationship', [relationship]),
)
}
const muteDomain = (store, domain) => {
return muteDomain({
domain,
credentials: useOAuthStore().token,
}).then(() => store.commit('addDomainMute', domain))
return store.rootState.api.backendInteractor
.muteDomain({ domain })
.then(() => store.commit('addDomainMute', domain))
}
const unmuteDomain = (store, domain) => {
return unmuteDomain({
domain,
credentials: useOAuthStore().token,
}).then(() => store.commit('removeDomainMute', domain))
return store.rootState.api.backendInteractor
.unmuteDomain({ domain })
.then(() => store.commit('removeDomainMute', domain))
}
export const mutations = {
@ -401,60 +385,55 @@ const users = {
})
},
fetchUser(store, id) {
return fetchUser({
id,
credentials: useOAuthStore().token,
}).then((user) => {
store.commit('addNewUsers', [user])
return user
})
return store.rootState.api.backendInteractor
.fetchUser({ id })
.then((user) => {
store.commit('addNewUsers', [user])
return user
})
},
fetchUserByName(store, name) {
return fetchUserByName({
name,
credentials: useOAuthStore().token,
}).then((user) => {
store.commit('addNewUsers', [user])
return user
})
return store.rootState.api.backendInteractor
.fetchUserByName({ name })
.then((user) => {
store.commit('addNewUsers', [user])
return user
})
},
fetchUserRelationship(store, id) {
if (store.state.currentUser) {
fetchUserRelationship({
id,
credentials: useOAuthStore().token,
}).then((relationships) =>
store.commit('updateUserRelationship', relationships),
)
store.rootState.api.backendInteractor
.fetchUserRelationship({ id })
.then((relationships) =>
store.commit('updateUserRelationship', relationships),
)
}
},
fetchUserInLists(store, id) {
if (store.state.currentUser) {
fetchUserInLists({
id,
credentials: useOAuthStore().token,
}).then((inLists) => store.commit('updateUserInLists', { id, inLists }))
store.rootState.api.backendInteractor
.fetchUserInLists({ id })
.then((inLists) => store.commit('updateUserInLists', { id, inLists }))
}
},
fetchBlocks(store, args) {
const { reset } = args || {}
const maxId = store.state.currentUser.blockIdsMaxId
return fetchBlocks({
maxId,
credentials: useOAuthStore().token,
}).then((blocks) => {
if (reset) {
store.commit('saveBlockIds', map(blocks, 'id'))
} else {
map(blocks, 'id').map((id) => store.commit('addBlockId', id))
}
if (blocks.length) {
store.commit('setBlockIdsMaxId', last(blocks).id)
}
store.commit('addNewUsers', blocks)
return blocks
})
return store.rootState.api.backendInteractor
.fetchBlocks({ maxId })
.then((blocks) => {
if (reset) {
store.commit('saveBlockIds', map(blocks, 'id'))
} else {
map(blocks, 'id').map((id) => store.commit('addBlockId', id))
}
if (blocks.length) {
store.commit('setBlockIdsMaxId', last(blocks).id)
}
store.commit('addNewUsers', blocks)
return blocks
})
},
blockUser(store, data) {
return blockUser(store, data)
@ -478,24 +457,23 @@ const users = {
const { reset } = args || {}
const maxId = store.state.currentUser.muteIdsMaxId
return fetchMutes({
maxId,
credentials: useOAuthStore().token,
}).then((mutes) => {
if (reset) {
store.commit('saveMuteIds', map(mutes, 'id'))
} else {
map(mutes, 'id').map((id) => store.commit('addMuteId', id))
}
if (mutes.length) {
store.commit('setMuteIdsMaxId', last(mutes).id)
}
store.commit('addNewUsers', mutes)
return mutes
})
return store.rootState.api.backendInteractor
.fetchMutes({ maxId })
.then((mutes) => {
if (reset) {
store.commit('saveMuteIds', map(mutes, 'id'))
} else {
map(mutes, 'id').map((id) => store.commit('addMuteId', id))
}
if (mutes.length) {
store.commit('setMuteIdsMaxId', last(mutes).id)
}
store.commit('addNewUsers', mutes)
return mutes
})
},
muteUser(store, data) {
return localMuteUser(store, data)
return muteUser(store, data)
},
unmuteUser(store, id) {
return unmuteUser(store, id)
@ -507,18 +485,18 @@ const users = {
return showReblogs(store, id)
},
muteUsers(store, data = []) {
return Promise.all(data.map((d) => localMuteUser(store, d)))
return Promise.all(data.map((d) => muteUser(store, d)))
},
unmuteUsers(store, ids = []) {
return Promise.all(ids.map((d) => unmuteUser(store, d)))
},
fetchDomainMutes(store) {
return fetchDomainMutes({
credentials: useOAuthStore().token,
}).then((domainMutes) => {
store.commit('saveDomainMutes', domainMutes)
return domainMutes
})
return store.rootState.api.backendInteractor
.fetchDomainMutes()
.then((domainMutes) => {
store.commit('saveDomainMutes', domainMutes)
return domainMutes
})
},
muteDomain(store, domain) {
return muteDomain(store, domain)
@ -535,28 +513,24 @@ const users = {
fetchFriends({ rootState, commit }, id) {
const user = rootState.users.usersObject[id]
const maxId = last(user.friendIds)
return fetchFriends({
id,
maxId,
credentials: useOAuthStore().token,
}).then((friends) => {
commit('addNewUsers', friends)
commit('saveFriendIds', { id, friendIds: map(friends, 'id') })
return friends
})
return rootState.api.backendInteractor
.fetchFriends({ id, maxId })
.then((friends) => {
commit('addNewUsers', friends)
commit('saveFriendIds', { id, friendIds: map(friends, 'id') })
return friends
})
},
fetchFollowers({ rootState, commit }, id) {
const user = rootState.users.usersObject[id]
const maxId = last(user.followerIds)
return fetchFollowers({
id,
maxId,
credentials: useOAuthStore().token,
}).then((followers) => {
commit('addNewUsers', followers)
commit('saveFollowerIds', { id, followerIds: map(followers, 'id') })
return followers
})
return rootState.api.backendInteractor
.fetchFollowers({ id, maxId })
.then((followers) => {
commit('addNewUsers', followers)
commit('saveFollowerIds', { id, followerIds: map(followers, 'id') })
return followers
})
},
clearFriends({ commit }, userId) {
commit('clearFriends', userId)
@ -565,22 +539,18 @@ const users = {
commit('clearFollowers', userId)
},
subscribeUser({ rootState, commit }, id) {
return followUser({
id,
notify: true,
credentials: useOAuthStore().token,
}).then((relationship) =>
commit('updateUserRelationship', [relationship]),
)
return rootState.api.backendInteractor
.followUser({ id, notify: true })
.then((relationship) =>
commit('updateUserRelationship', [relationship]),
)
},
unsubscribeUser({ rootState, commit }, id) {
return followUser({
id,
notify: false,
credentials: useOAuthStore().token,
}).then((relationship) =>
commit('updateUserRelationship', [relationship]),
)
return rootState.api.backendInteractor
.followUser({ id, notify: false })
.then((relationship) =>
commit('updateUserRelationship', [relationship]),
)
},
registerPushNotifications(store) {
const token = store.state.currentUser.credentials
@ -641,13 +611,12 @@ const users = {
})
},
searchUsers({ rootState, commit }, { query }) {
return searchUsers({
query,
credentials: useOAuthStore().token,
}).then((users) => {
commit('addNewUsers', users)
return users
})
return rootState.api.backendInteractor
.searchUsers({ query })
.then((users) => {
commit('addNewUsers', users)
return users
})
},
async signUp(store, userInfo) {
const oauthStore = useOAuthStore()
@ -655,7 +624,7 @@ const users = {
try {
const token = await oauthStore.ensureAppToken()
const data = await register({
const data = await apiService.register({
credentials: token,
params: { ...userInfo },
})
@ -676,10 +645,8 @@ const users = {
throw e
}
},
getCaptcha(store) {
return getCaptcha({
credentials: useOAuthStore().token,
})
async getCaptcha(store) {
return store.rootState.api.backendInteractor.getCaptcha()
},
logout(store) {
@ -703,9 +670,13 @@ const users = {
store.dispatch('disconnectFromSocket')
oauth.clearToken()
store.dispatch('stopFetchingTimeline', 'friends')
store.commit(
'setBackendInteractor',
backendInteractorService(oauth.getToken),
)
store.dispatch('stopFetchingNotifications')
useListsStore().stopFetching()
useBookmarkFoldersStore().stopFetching()
store.dispatch('stopFetchingLists')
store.dispatch('stopFetchingBookmarkFolders')
store.dispatch('stopFetchingFollowRequests')
store.commit('clearNotifications')
store.commit('resetStatuses')
@ -719,12 +690,9 @@ const users = {
return new Promise((resolve, reject) => {
const commit = store.commit
const dispatch = store.dispatch
commit('beginLogin')
verifyCredentials({
credentials: useOAuthStore().token,
})
store.rootState.api.backendInteractor
.verifyCredentials(accessToken)
.then((data) => {
if (!data.error) {
const user = data
@ -753,6 +721,12 @@ const users = {
useInterfaceStore().setNotificationPermission(permission),
)
// Set our new backend interactor
commit(
'setBackendInteractor',
backendInteractorService(accessToken),
)
// Do server-side storage migrations
// Debug snippet to clean up storage and reset migrations
@ -790,8 +764,8 @@ const users = {
}
}
useListsStore().startFetching()
useBookmarkFoldersStore().startFetching()
dispatch('startFetchingLists')
dispatch('startFetchingBookmarkFolders')
if (user.locked) {
dispatch('startFetchingFollowRequests')
@ -825,9 +799,9 @@ const users = {
useInterfaceStore().setLayoutHeight(windowHeight())
// Fetch our friends
fetchFriends({ id: user.id }).then((friends) =>
commit('addNewUsers', friends),
)
store.rootState.api.backendInteractor
.fetchFriends({ id: user.id })
.then((friends) => commit('addNewUsers', friends))
} else {
const response = data.error
// Authentication failed

View file

@ -1,509 +0,0 @@
import { promisedRequest } from './helpers.js'
import { RegistrationError, StatusCodeError } from 'src/services/errors/errors'
const REPORTS = '/api/v1/pleroma/admin/reports'
const CONFIG_URL = '/api/v1/pleroma/admin/config'
const DESCRIPTIONS_URL = '/api/v1/pleroma/admin/config/descriptions'
const ANNOUNCEMENTS_URL = (id = '') =>
`/api/v1/pleroma/admin/announcements/${id}`
const FRONTENDS_URL = '/api/v1/pleroma/admin/frontends'
const FRONTENDS_INSTALL_URL = '/api/v1/pleroma/admin/frontends/install'
const USERS_URL = (nickname = '') => `/api/v1/pleroma/admin/users/${nickname}`
const USERS_URL_LIST = ({
page,
pageSize,
filters = {},
query = '',
name = '',
email = '',
}) => {
const {
local = false,
external = false,
active = false,
needApproval = false,
unconfirmed = false,
deactivated = false,
isAdmin = true,
isModerator = true,
} = filters
const filters_str = [
local && 'local',
external && 'external',
active && 'active',
needApproval && 'need_approval',
unconfirmed && 'unconfirmed',
deactivated && 'deactivated',
isAdmin && 'is_admin',
isModerator && 'is_moderator',
]
.filter((x) => x)
.join(',')
return `/api/v1/pleroma/admin/users?page=${page}&page_size=${pageSize}&filters=${filters_str}&query=${query}&name=${name}&email=${email}`
}
const TAG_USER_URL = '/api/pleroma/admin/users/tag'
const PERMISSION_GROUP_URL = (right) =>
`/api/pleroma/admin/users/permission_group/${right}`
const ACTIVATE_USERS_URL = '/api/pleroma/admin/users/activate'
const DEACTIVATE_USERS_URL = '/api/pleroma/admin/users/deactivate'
const SUGGEST_USERS_URL = '/api/pleroma/admin/users/suggest'
const UNSUGGEST_USERS_URL = '/api/pleroma/admin/users/unsuggest'
const APPROVE_USERS_URL = '/api/v1/pleroma/admin/users/approve'
const CONFIRM_USERS_URL = '/api/v1/pleroma/admin/users/confirm_email'
const RESEND_CONFIRMATION_EMAIL_URL =
'/api/v1/pleroma/admin/users/resend_confirmation_email'
const LIST_STATUSES_URL = ({ id, page, pageSize, godmode, withReblogs }) =>
`/api/v1/pleroma/admin/users/${id}/statuses?page_size=${pageSize}&page=${page}&godmode=${godmode}&with_reblogs=${withReblogs}`
const CHANGE_STATUS_SCOPE_URL = (id) => `/api/v1/pleroma/admin/statuses/${id}`
const REQUIRE_PASSWORD_CHANGE_URL =
'/api/v1/pleroma/admin/users/force_password_reset'
const DISABLE_MFA_URL = '/api/v1/pleroma/admin/users/disable_mfa'
const EMOJI_RELOAD_URL = '/api/pleroma/admin/reload_emoji'
const EMOJI_IMPORT_FS_URL = '/api/pleroma/emoji/packs/import'
const EMOJI_PACK_URL = (name) => `/api/v1/pleroma/emoji/pack?name=${name}`
const EMOJI_PACKS_DL_REMOTE_URL = '/api/v1/pleroma/emoji/packs/download'
const EMOJI_PACKS_DL_REMOTE_ZIP_URL = '/api/v1/pleroma/emoji/packs/download_zip'
const EMOJI_PACKS_LS_REMOTE_URL = (url, page, pageSize) =>
`/api/v1/pleroma/emoji/packs/remote?url=${url}&page=${page}&page_size=${pageSize}`
const EMOJI_UPDATE_FILE_URL = (name) =>
`/api/v1/pleroma/emoji/packs/files?name=${name}`
//
export const setUsersTags = ({
tags,
credentials,
value,
screen_names: nicknames,
}) =>
promisedRequest({
url: TAG_USER_URL,
method: value ? 'PUT' : 'DELETE',
credentials,
payload: {
nicknames,
tags,
},
})
export const setUsersRight = ({
right,
credentials,
value,
screen_names: nicknames,
}) =>
promisedRequest({
url: PERMISSION_GROUP_URL(right),
method: value ? 'POST' : 'DELETE',
credentials,
payload: {
nicknames,
},
})
export const setUsersActivationStatus = ({
credentials,
screen_names: nicknames,
value,
}) =>
promisedRequest({
url: value ? ACTIVATE_USERS_URL : DEACTIVATE_USERS_URL,
method: 'PATCH',
credentials,
payload: {
nicknames,
},
}).then((response) => response.users)
export const setUsersApprovalStatus = ({
credentials,
screen_names: nicknames,
}) =>
promisedRequest({
url: APPROVE_USERS_URL,
method: 'PATCH',
credentials,
payload: {
nicknames,
},
}).then((response) => response.users)
export const setUsersConfirmationStatus = ({
credentials,
screen_names: nicknames,
}) =>
promisedRequest({
url: CONFIRM_USERS_URL,
method: 'PATCH',
credentials,
payload: {
nicknames,
},
}).then((response) => response.users)
export const setUsersSuggestionStatus = ({
credentials,
screen_names: nicknames,
value,
}) =>
promisedRequest({
url: value ? SUGGEST_USERS_URL : UNSUGGEST_USERS_URL,
method: 'PATCH',
credentials,
payload: {
nicknames,
},
}).then((response) => response.users)
export const getUserData = ({ credentials, screen_name: nickname }) =>
promisedRequest({
url: USERS_URL(nickname),
method: 'GET',
credentials,
})
export const deleteAccounts = ({ credentials, screen_names: nicknames }) =>
promisedRequest({
url: USERS_URL(),
method: 'DELETE',
credentials,
payload: {
nicknames,
},
})
export const getAnnouncements = ({ id, credentials }) =>
promisedRequest({ url: ANNOUNCEMENTS_URL(id), credentials })
// the reported list is hardly useful because standards are for dating i guess,
// so make sure to fetchIfMissing right afterward using this call
export const listUsers = ({ opts, credentials }) =>
promisedRequest({
url: USERS_URL_LIST(opts),
credentials,
method: 'GET',
})
export const resendConfirmationEmail = ({
screen_names: nicknames,
credentials,
}) =>
promisedRequest({
url: RESEND_CONFIRMATION_EMAIL_URL,
credentials,
method: 'PATCH',
payload: {
nicknames,
},
})
export const requirePasswordChange = ({
screen_names: nicknames,
credentials,
}) =>
promisedRequest({
url: REQUIRE_PASSWORD_CHANGE_URL,
credentials,
method: 'PATCH',
payload: {
nicknames,
},
})
export const disableMFA = ({ screen_name: nickname, credentials }) =>
promisedRequest({
url: DISABLE_MFA_URL,
credentials,
method: 'PUT',
payload: {
nickname,
},
})
export const listStatuses = ({ opts, credentials }) =>
promisedRequest({
url: LIST_STATUSES_URL(opts),
credentials,
method: 'GET',
})
export const changeStatusScope = ({
opts: { id, sensitive, visibility },
credentials,
}) => {
var payload = {}
if (typeof sensitive !== 'undefined') {
payload['sensitive'] = sensitive
}
if (typeof visibility !== 'undefined') {
payload['visibility'] = visibility
}
return promisedRequest({
url: CHANGE_STATUS_SCOPE_URL(id),
credentials,
method: 'PUT',
payload,
})
}
export const announcementToPayload = ({
content,
startsAt,
endsAt,
allDay,
}) => {
const payload = { content }
if (typeof startsAt !== 'undefined') {
payload.starts_at = startsAt ? new Date(startsAt).toISOString() : null
}
if (typeof endsAt !== 'undefined') {
payload.ends_at = endsAt ? new Date(endsAt).toISOString() : null
}
if (typeof allDay !== 'undefined') {
payload.all_day = allDay
}
return payload
}
export const postAnnouncement = ({
credentials,
content,
startsAt,
endsAt,
allDay,
}) =>
promisedRequest({
url: ANNOUNCEMENTS_URL(),
credentials,
method: 'POST',
payload: announcementToPayload({ content, startsAt, endsAt, allDay }),
})
export const editAnnouncement = ({
id,
credentials,
content,
startsAt,
endsAt,
allDay,
}) =>
promisedRequest({
url: ANNOUNCEMENTS_URL(id),
credentials,
method: 'PATCH',
payload: announcementToPayload({ content, startsAt, endsAt, allDay }),
})
export const deleteAnnouncement = ({ id, credentials }) =>
promisedRequest({
url: ANNOUNCEMENTS_URL(id),
credentials,
method: 'DELETE',
})
export const setReportState = ({ id, state, credentials }) => {
// TODO: Can't use promisedRequest because on OK this does not return json
// See https://git.pleroma.social/pleroma/pleroma-fe/-/merge_requests/1322
return promisedRequest({
url: REPORTS,
credentials,
method: 'PATCH',
payload: {
reports: [
{
id,
state,
},
],
},
})
.then((data) => {
if (data.status >= 500) {
throw Error(data.statusText)
} else if (data.status >= 400) {
return data.json()
}
return data
})
.then((data) => {
if (data.errors) {
throw Error(data.errors[0].message)
}
})
}
export const getInstanceDBConfig = ({ credentials }) =>
promisedRequest({
url: CONFIG_URL,
credentials,
})
export const getInstanceConfigDescriptions = ({ credentials }) =>
promisedRequest({
url: DESCRIPTIONS_URL,
credentials,
})
export const getAvailableFrontends = ({ credentials }) =>
promisedRequest({
url: FRONTENDS_URL,
credentials,
})
export const pushInstanceDBConfig = ({ credentials, payload }) =>
promisedRequest({
url: CONFIG_URL,
method: 'POST',
credentials,
payload,
})
export const installFrontend = ({ credentials, payload }) =>
promisedRequest({
url: FRONTENDS_INSTALL_URL,
credentials,
method: 'POST',
payload,
})
// Emoji packs
export const deleteEmojiPack = ({ name }) =>
promisedRequest({
url: EMOJI_PACK_URL(name),
method: 'DELETE',
})
export const reloadEmoji = ({ credentials }) =>
promisedRequest({
url: EMOJI_RELOAD_URL,
method: 'POST',
credentials,
})
export const importEmojiFromFS = ({ credentials }) =>
promisedRequest({
url: EMOJI_IMPORT_FS_URL,
credentials,
})
export const createEmojiPack = ({ name, credentials }) =>
promisedRequest({
url: EMOJI_PACK_URL(name),
method: 'POST',
credentials,
})
export const listRemoteEmojiPacks = ({
instance,
page,
pageSize,
credentials,
}) => {
if (!instance.startsWith('http')) {
instance = 'https://' + instance
}
return promisedRequest({
url: EMOJI_PACKS_LS_REMOTE_URL(instance, page, pageSize),
credentials,
})
}
export const downloadRemoteEmojiPack = ({
instance,
packName,
as,
credentials,
}) =>
promisedRequest({
url: EMOJI_PACKS_DL_REMOTE_URL,
credentials,
method: 'POST',
payload: {
url: instance,
name: packName,
as,
},
})
export const downloadRemoteEmojiPackZIP = ({
url,
packName,
file,
credentials,
}) => {
const data = new FormData()
if (file) data.set('file', file)
if (url) data.set('url', url)
data.set('name', packName)
return promisedRequest({
url: EMOJI_PACKS_DL_REMOTE_ZIP_URL,
method: 'POST',
payload: data,
})
}
export const saveEmojiPackMetadata = ({ name, newData, credentials }) =>
promisedRequest({
url: EMOJI_PACK_URL(name),
credentials,
method: 'PATCH',
payload: { metadata: newData },
})
export const addNewEmojiFile = ({ packName, file, shortcode, filename }) => {
const data = new FormData()
if (filename.trim() !== '') {
data.set('filename', filename)
}
if (shortcode.trim() !== '') {
data.set('shortcode', shortcode)
}
data.set('file', file)
return promisedRequest({
url: EMOJI_UPDATE_FILE_URL(packName),
method: 'POST',
payload: data,
})
}
export const updateEmojiFile = ({
packName,
shortcode,
newShortcode,
newFilename,
credentials,
force,
}) =>
promisedRequest({
url: EMOJI_UPDATE_FILE_URL(packName),
credentials,
method: 'PATCH',
payload: {
shortcode,
new_shortcode: newShortcode,
new_filename: newFilename,
force,
},
})
export const deleteEmojiFile = ({ packName, shortcode }) =>
promisedRequest({
url: `${EMOJI_UPDATE_FILE_URL(packName)}&shortcode=${shortcode}`,
method: 'DELETE',
})

File diff suppressed because it is too large Load diff

View file

@ -1,87 +0,0 @@
import { RegistrationError, StatusCodeError } from 'src/services/errors/errors'
export const promisedRequest = ({
method,
url,
params,
payload,
formData,
credentials,
headers = {},
}) => {
const options = {
method,
credentials: 'same-origin',
headers: {
Accept: 'application/json',
...headers,
},
}
if (!formData) {
options.headers['Content-Type'] = 'application/json'
}
if (params) {
url +=
'?' +
Object.entries(params)
.map(
([key, value]) =>
encodeURIComponent(key) + '=' + encodeURIComponent(value),
)
.join('&')
}
if (formData || payload) {
options.body = formData || JSON.stringify(payload)
}
if (credentials) {
options.headers = {
...options.headers,
...authHeaders(credentials),
}
}
return fetch(url, options).then((response) => {
return new Promise((resolve, reject) => {
// 204 is "No content", which fails to parse json (as you'd might think)
if (response.ok && response.status === 204) resolve()
return response
.json()
.then((json) => {
if (!response.ok) {
return reject(
new StatusCodeError(
response.status,
json,
{ url, options },
response,
),
)
}
json._response = response
return resolve(json)
})
.catch((error) => {
return reject(
new StatusCodeError(
response.status,
error,
{ url, options },
response,
),
)
})
})
})
}
const authHeaders = (accessToken) => {
if (accessToken) {
return { Authorization: `Bearer ${accessToken}` }
} else {
return {}
}
}

View file

@ -0,0 +1,75 @@
import bookmarkFoldersFetcher from '../../services/bookmark_folders_fetcher/bookmark_folders_fetcher.service.js'
import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
import listsFetcher from '../../services/lists_fetcher/lists_fetcher.service.js'
import apiService, {
getMastodonSocketURI,
ProcessedWS,
} from '../api/api.service.js'
import notificationsFetcher from '../notifications_fetcher/notifications_fetcher.service.js'
import timelineFetcher from '../timeline_fetcher/timeline_fetcher.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
const backendInteractorService = (credentials) => ({
startFetchingTimeline({
timeline,
store,
userId = false,
listId = false,
statusId = false,
bookmarkFolderId = false,
tag,
}) {
return timelineFetcher.startFetching({
timeline,
store,
credentials,
userId,
listId,
statusId,
bookmarkFolderId,
tag,
})
},
fetchTimeline(args) {
return timelineFetcher.fetchAndUpdate({ ...args, credentials })
},
startFetchingNotifications({ store }) {
return notificationsFetcher.startFetching({ store, credentials })
},
fetchNotifications(args) {
return notificationsFetcher.fetchAndUpdate({ ...args, credentials })
},
startFetchingFollowRequests({ store }) {
return followRequestFetcher.startFetching({ store, credentials })
},
startFetchingLists({ store }) {
return listsFetcher.startFetching({ store, credentials })
},
startFetchingBookmarkFolders({ store }) {
return bookmarkFoldersFetcher.startFetching({ store, credentials })
},
startUserSocket({ store }) {
const serv = useInstanceStore().server.replace('http', 'ws')
const url = getMastodonSocketURI({}, serv)
return ProcessedWS({ url, id: 'Unified', credentials })
},
...Object.entries(apiService).reduce((acc, [key, func]) => {
return {
...acc,
[key]: (args) => func({ credentials, ...args }),
}
}, {}),
verifyCredentials: apiService.verifyCredentials,
})
export default backendInteractorService

View file

@ -0,0 +1,32 @@
import apiService from '../api/api.service.js'
import { promiseInterval } from '../promise_interval/promise_interval.js'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
const fetchAndUpdate = ({ credentials }) => {
return apiService
.fetchBookmarkFolders({ credentials })
.then(
(bookmarkFolders) => {
useBookmarkFoldersStore().setBookmarkFolders(bookmarkFolders)
},
(rej) => {
console.error(rej)
},
)
.catch((e) => {
console.error(e)
})
}
const startFetching = ({ credentials, store }) => {
const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
boundFetchAndUpdate()
return promiseInterval(boundFetchAndUpdate, 240000)
}
const bookmarkFoldersFetcher = {
startFetching,
}
export default bookmarkFoldersFetcher

View file

@ -1,18 +1,8 @@
import { useOAuthStore } from 'src/stores/oauth.js'
import {
fetchUserRelationship,
followUser,
unfollowUser,
} from 'src/services/api/api.service.js'
const fetchRelationship = (attempt, userId, store) =>
new Promise((resolve, reject) => {
setTimeout(() => {
fetchUserRelationship({
id: userId,
credentials: useOAuthStore().token,
})
store.state.api.backendInteractor
.fetchUserRelationship({ id: userId })
.then((relationship) => {
store.commit('updateUserRelationship', [relationship])
return relationship
@ -37,40 +27,38 @@ const fetchRelationship = (attempt, userId, store) =>
export const requestFollow = (userId, store) =>
new Promise((resolve) => {
followUser({
id: userId,
credentials: useOAuthStore().token,
}).then((updated) => {
store.commit('updateUserRelationship', [updated])
store.state.api.backendInteractor
.followUser({ id: userId })
.then((updated) => {
store.commit('updateUserRelationship', [updated])
if (updated.following || (updated.locked && updated.requested)) {
// If we get result immediately or the account is locked, just stop.
resolve()
return
}
if (updated.following || (updated.locked && updated.requested)) {
// If we get result immediately or the account is locked, just stop.
resolve()
return
}
// But usually we don't get result immediately, so we ask server
// for updated user profile to confirm if we are following them
// Sometimes it takes several tries. Sometimes we end up not following
// user anyway, probably because they locked themselves and we
// don't know that yet.
// Recursive Promise, it will call itself up to 3 times.
// But usually we don't get result immediately, so we ask server
// for updated user profile to confirm if we are following them
// Sometimes it takes several tries. Sometimes we end up not following
// user anyway, probably because they locked themselves and we
// don't know that yet.
// Recursive Promise, it will call itself up to 3 times.
return fetchRelationship(1, updated, store).then(() => {
resolve()
return fetchRelationship(1, updated, store).then(() => {
resolve()
})
})
})
})
export const requestUnfollow = (userId, store) =>
new Promise((resolve) => {
unfollowUser({
id: userId,
credentials: useOAuthStore().token,
}).then((updated) => {
store.commit('updateUserRelationship', [updated])
resolve({
updated,
store.state.api.backendInteractor
.unfollowUser({ id: userId })
.then((updated) => {
store.commit('updateUserRelationship', [updated])
resolve({
updated,
})
})
})
})

View file

@ -1,8 +1,9 @@
import { fetchFollowRequests } from '../api/api.service.js'
import apiService from '../api/api.service.js'
import { promiseInterval } from '../promise_interval/promise_interval.js'
const fetchAndUpdate = ({ store, credentials }) => {
return fetchFollowRequests({ credentials })
return apiService
.fetchFollowRequests({ credentials })
.then(
(requests) => {
store.commit('setFollowRequests', requests)

View file

@ -0,0 +1,32 @@
import apiService from '../api/api.service.js'
import { promiseInterval } from '../promise_interval/promise_interval.js'
import { useListsStore } from 'src/stores/lists.js'
const fetchAndUpdate = ({ credentials }) => {
return apiService
.fetchLists({ credentials })
.then(
(lists) => {
useListsStore().setLists(lists)
},
(rej) => {
console.error(rej)
},
)
.catch((e) => {
console.error(e)
})
}
const startFetching = ({ credentials, store }) => {
const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
boundFetchAndUpdate()
return promiseInterval(boundFetchAndUpdate, 240000)
}
const listsFetcher = {
startFetching,
}
export default listsFetcher

View file

@ -1,4 +1,4 @@
import { fetchTimeline } from '../api/api.service.js'
import apiService from '../api/api.service.js'
import { promiseInterval } from '../promise_interval/promise_interval.js'
import { useInstanceStore } from 'src/stores/instance.js'
@ -80,7 +80,8 @@ const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
}
const fetchNotifications = ({ store, args, older }) => {
return fetchTimeline(args)
return apiService
.fetchTimeline(args)
.then((response) => {
if (response.errors) {
if (

View file

@ -4,39 +4,32 @@
// time after the first interval.
// - interval is the interval delay in ms.
const wait = (timeout) => {
let timeoutId
const promise = () =>
new Promise((resolve) => {
timeoutId = window.setTimeout(() => resolve(), timeout)
})
return { timeoutId, promise }
}
export const promiseInterval = (promiseCall, interval) => {
let stopped = false
let timeout = null
const func = () => {
const promise = promiseCall()
// something unexpected happened and promiseCall did not
// return a promise, abort the loop.
if (!(promise && promise.finally)) {
console.warn(
'promiseInterval: promise call did not return a promise, stopping interval.',
)
return
}
promise.finally(() => {
if (stopped) return
timeout = window.setTimeout(func, interval)
})
}
const stopFetcher = () => {
stopped = true
window.clearTimeout(timeout)
}
const loop = new Promise(async (resolve, reject) => {
try {
while (!stopped) {
await promiseCall()
const { timeoutId, promise } = wait(interval)
timeout = timeoutId
await promise()
}
resolve()
} catch (e) {
reject(e)
}
})
loop.then()
timeout = window.setTimeout(func, interval)
return { stop: stopFetcher }
}

View file

@ -1,11 +1,6 @@
import { map } from 'lodash'
import {
editStatus as apiEditStatus,
postStatus as apiPostStatus,
setMediaDescription as apiSetMediaDescription,
uploadMedia as apiUploadMedia,
} from '../api/api.service.js'
import apiService from '../api/api.service.js'
const postStatus = ({
store,
@ -23,20 +18,21 @@ const postStatus = ({
}) => {
const mediaIds = map(media, 'id')
return apiPostStatus({
credentials: store.state.users.currentUser.credentials,
status,
spoilerText,
visibility,
sensitive,
mediaIds,
inReplyToStatusId,
quoteId,
contentType,
poll,
preview,
idempotencyKey,
})
return apiService
.postStatus({
credentials: store.state.users.currentUser.credentials,
status,
spoilerText,
visibility,
sensitive,
mediaIds,
inReplyToStatusId,
quoteId,
contentType,
poll,
preview,
idempotencyKey,
})
.then((data) => {
if (!data.error && !preview) {
store.dispatch('addNewStatuses', {
@ -67,16 +63,17 @@ const editStatus = ({
}) => {
const mediaIds = map(media, 'id')
return editStatus({
id: statusId,
credentials: store.state.users.currentUser.credentials,
status,
spoilerText,
sensitive,
poll,
mediaIds,
contentType,
})
return apiService
.editStatus({
id: statusId,
credentials: store.state.users.currentUser.credentials,
status,
spoilerText,
sensitive,
poll,
mediaIds,
contentType,
})
.then((data) => {
if (!data.error) {
store.dispatch('addNewStatuses', {
@ -98,12 +95,12 @@ const editStatus = ({
const uploadMedia = ({ store, formData }) => {
const credentials = store.state.users.currentUser.credentials
return apiUploadMedia({ credentials, formData })
return apiService.uploadMedia({ credentials, formData })
}
const setMediaDescription = ({ store, id, description }) => {
const credentials = store.state.users.currentUser.credentials
return apiSetMediaDescription({ credentials, id, description })
return apiService.setMediaDescription({ credentials, id, description })
}
const statusPosterService = {

View file

@ -1,6 +1,6 @@
import { camelCase } from 'lodash'
import { fetchTimeline } from '../api/api.service.js'
import apiService from '../api/api.service.js'
import { promiseInterval } from '../promise_interval/promise_interval.js'
import { useInstanceStore } from 'src/stores/instance.js'
@ -75,7 +75,8 @@ const fetchAndUpdate = ({
const numStatusesBeforeFetch = timelineData.statuses.length
return fetchTimeline(args)
return apiService
.fetchTimeline(args)
.then((response) => {
if (response.errors) {
if (timeline === 'favorites') {

View file

@ -1,38 +1,6 @@
import { cloneDeep, differenceWith, flatten, get, isEqual, set } from 'lodash'
import { defineStore } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
addNewEmojiFile,
changeStatusScope,
createEmojiPack,
deleteAccounts,
deleteEmojiPack,
disableMFA,
downloadRemoteEmojiPack,
downloadRemoteEmojiPackZIP,
getAvailableFrontends,
getInstanceConfigDescriptions,
getInstanceDBConfig,
getUserData,
importEmojiFromFS,
installFrontend,
listRemoteEmojiPacks,
listStatuses,
listUsers,
pushInstanceDBConfig,
reloadEmoji,
requirePasswordChange,
resendConfirmationEmail,
setUsersActivationStatus,
setUsersApprovalStatus,
setUsersConfirmationStatus,
setUsersRight,
setUsersSuggestionStatus,
setUsersTags,
} from 'src/services/api/admin.js'
import { listEmojiPacks } from 'src/services/api/api.service.js'
import { parseStatus } from 'src/services/entity_normalizer/entity_normalizer.service.js'
export const defaultState = {
@ -53,6 +21,7 @@ export const newUserFlags = {
export const useAdminSettingsStore = defineStore('adminSettings', {
state: () => ({
...cloneDeep(defaultState),
backendInteractor: window.vuex.state.api.backendInteractor,
}),
actions: {
// Configuration Stuff
@ -85,9 +54,7 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
},
loadAdminStuff() {
getInstanceDBConfig({
credentials: useOAuthStore().token,
}).then((backendDbConfig) => {
this.backendInteractor.fetchInstanceDBConfig().then((backendDbConfig) => {
if (backendDbConfig.error) {
if (backendDbConfig.error.status === 400) {
backendDbConfig.error.json().then((errorJson) => {
@ -97,21 +64,15 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
})
}
} else {
this.setInstanceAdminSettings({
credentials: useOAuthStore().token,
backendDbConfig,
})
this.setInstanceAdminSettings({ backendDbConfig })
}
})
if (this.descriptions === null) {
getInstanceConfigDescriptions({
credentials: useOAuthStore().token,
}).then((backendDescriptions) =>
this.setInstanceAdminDescriptions({
credentials: useOAuthStore().token,
backendDescriptions,
}),
)
this.backendInteractor
.fetchInstanceConfigDescriptions()
.then((backendDescriptions) =>
this.setInstanceAdminDescriptions({ backendDescriptions }),
)
}
},
setInstanceAdminSettings({ backendDbConfig }) {
@ -242,23 +203,17 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
}
})
pushInstanceDBConfig({
credentials: useOAuthStore().token,
payload: {
configs: changed,
},
})
window.vuex.state.api.backendInteractor
.pushInstanceDBConfig({
payload: {
configs: changed,
},
})
.then(() =>
getInstanceDBConfig({
credentials: useOAuthStore().token,
}),
window.vuex.state.api.backendInteractor.fetchInstanceDBConfig(),
)
.then((backendDbConfig) =>
this.setInstanceAdminSettings({
credentials: useOAuthStore().token,
backendDbConfig,
}),
this.setInstanceAdminSettings({ backendDbConfig }),
)
},
pushAdminSetting({ path, value }) {
@ -279,28 +234,23 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
}
}
pushInstanceDBConfig({
credentials: useOAuthStore().token,
payload: {
configs: [
{
group,
key,
value: convert(clone),
},
],
},
})
window.vuex.state.api.backendInteractor
.pushInstanceDBConfig({
payload: {
configs: [
{
group,
key,
value: convert(clone),
},
],
},
})
.then(() =>
getInstanceDBConfig({
credentials: useOAuthStore().token,
}),
window.vuex.state.api.backendInteractor.fetchInstanceDBConfig(),
)
.then((backendDbConfig) =>
this.setInstanceAdminSettings({
credentials: useOAuthStore().token,
backendDbConfig,
}),
this.setInstanceAdminSettings({ backendDbConfig }),
)
},
resetAdminSetting({ path }) {
@ -310,23 +260,21 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
this.modifiedPaths.delete(path)
return pushInstanceDBConfig({
credentials: useOAuthStore().token,
payload: {
configs: [
{
group,
key,
delete: true,
subkeys: [subkey],
},
],
},
})
return window.vuex.state.api.backendInteractor
.pushInstanceDBConfig({
payload: {
configs: [
{
group,
key,
delete: true,
subkeys: [subkey],
},
],
},
})
.then(() =>
getInstanceDBConfig({
credentials: useOAuthStore().token,
}),
window.vuex.state.api.backendInteractor.fetchInstanceDBConfig(),
)
.then((backendDbConfig) =>
this.setInstanceAdminSettings({ backendDbConfig }),
@ -335,9 +283,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
// Frontends Stuff
loadFrontendsStuff() {
getAvailableFrontends({
credentials: useOAuthStore().token,
}).then((frontends) => this.setAvailableFrontends({ frontends }))
this.backendInteractor
.fetchAvailableFrontends()
.then((frontends) => this.setAvailableFrontends({ frontends }))
},
setAvailableFrontends({ frontends }) {
@ -352,18 +300,12 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
})
},
installFrontend() {
return installFrontend({
credentials: useOAuthStore().token,
})
},
// Statuses stuff
async fetchStatuses(opts) {
const { total, activities } = await listStatuses({
credentials: useOAuthStore().token,
opts,
})
const { total, activities } =
await this.backendInteractor.adminListStatuses({
opts,
})
const statuses = activities.map(parseStatus)
@ -375,8 +317,7 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
}
},
async changeStatusScope(opts) {
const raw = await changeStatusScope({
credentials: useOAuthStore().token,
const raw = await this.backendInteractor.adminChangeStatusScope({
opts,
})
const status = parseStatus(raw)
@ -386,9 +327,7 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
// Users stuff
async fetchUsers(opts) {
const { users, count } = await listUsers({
credentials: useOAuthStore().token,
const { users, count } = await this.backendInteractor.adminListUsers({
opts,
})
@ -405,23 +344,17 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
}
},
async getUserData({ user }) {
const api = getUserData
const api = this.backendInteractor.adminGetUserData
const { screen_name } = user
const result = await api({
credentials: useOAuthStore().token,
screen_name,
})
const result = await api({ screen_name })
window.vuex.commit('updateUserAdminData', { user: result })
},
async deleteUsers({ users }) {
const screen_names = users.map((u) => u.screen_name)
const api = deleteAccounts
const api = this.backendInteractor.adminDeleteAccounts
const resultUserIds = await api({
credentials: useOAuthStore().token,
screen_names,
})
const resultUserIds = await api({ screen_names })
resultUserIds.forEach((userId) => {
window.vuex.dispatch(
@ -436,16 +369,14 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
resendConfirmationEmail({ users }) {
const screen_names = users.map((u) => u.screen_name)
return resendConfirmationEmail({
credentials: useOAuthStore().token,
return this.backendInteractor.adminResendConfirmationEmail({
screen_names,
})
},
requirePasswordChange({ users }) {
const screen_names = users.map((u) => u.screen_name)
return requirePasswordChange({
credentials: useOAuthStore().token,
return this.backendInteractor.adminRequirePasswordChange({
screen_names,
})
},
@ -453,17 +384,13 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
disableMFA({ user }) {
const { screen_name } = user
return disableMFA({
credentials: useOAuthStore().token,
screen_name,
})
return this.backendInteractor.adminDisableMFA({ screen_name })
},
async setUsersTags({ users, tags, value }) {
const screen_names = users.map((u) => u.screen_name)
const api = setUsersTags
const api = this.backendInteractor.adminSetUsersTags
await api({
credentials: useOAuthStore().token,
screen_names,
tags,
value,
@ -475,10 +402,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
},
async setUsersRight({ users, right, value }) {
const screen_names = users.map((u) => u.screen_name)
const api = setUsersRight
const api = this.backendInteractor.adminSetUsersRight
await api({
credentials: useOAuthStore().token,
screen_names,
right,
value,
@ -490,10 +416,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
},
async setUsersActivationStatus({ users, value }) {
const screen_names = users.map((u) => u.screen_name)
const api = setUsersActivationStatus
const api = this.backendInteractor.adminSetUsersActivationStatus
const resultUsers = await api({
credentials: useOAuthStore().token,
screen_names,
value,
})
@ -504,10 +429,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
},
async setUsersSuggestionStatus({ users, value }) {
const screen_names = users.map((u) => u.screen_name)
const api = setUsersSuggestionStatus
const api = this.backendInteractor.adminSetUsersSuggestionStatus
const resultUsers = await api({
credentials: useOAuthStore().token,
screen_names,
value,
})
@ -518,12 +442,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
},
async setUsersConfirmationStatus({ users }) {
const screen_names = users.map((u) => u.screen_name)
const api = setUsersConfirmationStatus
const api = this.backendInteractor.adminSetUsersConfirmationStatus
await api({
credentials: useOAuthStore().token,
screen_names,
})
await api({ screen_names })
users.forEach((user) => {
this.getUserData({ user })
@ -531,10 +452,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
},
async setUsersApprovalStatus({ users }) {
const screen_names = users.map((u) => u.screen_name)
const api = setUsersApprovalStatus
const api = this.backendInteractor.adminSetUsersApprovalStatus
const resultUsers = await api({
credentials: useOAuthStore().token,
screen_names,
})
@ -542,66 +462,5 @@ export const useAdminSettingsStore = defineStore('adminSettings', {
window.vuex.commit('updateUserAdminData', { user })
})
},
reloadEmoji() {
return reloadEmoji({ credentials: useOAuthStore().token })
},
importEmojiFromFS() {
return importEmojiFromFS({ credentials: useOAuthStore().token })
},
listEmojiPacks(params) {
return listEmojiPacks({
...params,
credentials: useOAuthStore().token,
})
},
listRemoteEmojiPacks(params) {
return listRemoteEmojiPacks({
...params,
credentials: useOAuthStore().token,
})
},
addNewEmojiFile({ packName, file, shortcode, filename }) {
return addNewEmojiFile({
packName,
file,
shortcode,
filename,
credentials: useOAuthStore().token,
})
},
downloadRemoteEmojiPack({ instance, packName, as }) {
return downloadRemoteEmojiPack({
instance,
packName,
as,
credentials: useOAuthStore().token,
})
},
downloadRemoteEmojiPackZIP({ url, packName }) {
return downloadRemoteEmojiPackZIP({
url,
packName,
credentials: useOAuthStore().token,
})
},
createEmojiPack({ name }) {
return createEmojiPack({
name,
credentials: useOAuthStore().token,
})
},
deleteEmojiPack({ name }) {
return createEmojiPack({
name,
credentials: useOAuthStore().token,
})
},
saveEmojiPackMetadata({ name, newData }) {
return createEmojiPack({
name,
newData,
credentials: useOAuthStore().token,
})
},
},
})

View file

@ -1,18 +1,5 @@
import { defineStore } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
getAnnouncements as adminGetAnnouncements,
deleteAnnouncement,
editAnnouncement,
postAnnouncement,
} from 'src/services/api/admin.js'
import {
dismissAnnouncement,
getAnnouncements,
} from 'src/services/api/api.service.js'
const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5
export const useAnnouncementsStore = defineStore('announcements', {
@ -44,19 +31,15 @@ export const useAnnouncementsStore = defineStore('announcements', {
currentUser &&
currentUser.privileges.has('announcements_manage_announcements')
const fetchAnnouncements = async () => {
const getAnnouncements = async () => {
if (!isAdmin) {
return getAnnouncements({
credentials: useOAuthStore().token,
})
return window.vuex.state.api.backendInteractor.fetchAnnouncements()
}
const all = await adminGetAnnouncements({
credentials: useOAuthStore().token,
})
const visible = await getAnnouncements({
credentials: useOAuthStore().token,
})
const all =
await window.vuex.state.api.backendInteractor.adminFetchAnnouncements()
const visible =
await window.vuex.state.api.backendInteractor.fetchAnnouncements()
const visibleObject = visible.reduce((a, c) => {
a[c.id] = c
return a
@ -76,7 +59,7 @@ export const useAnnouncementsStore = defineStore('announcements', {
return all
}
return fetchAnnouncements()
return getAnnouncements()
.then((announcements) => {
this.announcements = announcements
})
@ -91,18 +74,17 @@ export const useAnnouncementsStore = defineStore('announcements', {
})
},
markAnnouncementAsRead(id) {
return dismissAnnouncement({
id,
credentials: useOAuthStore().token,
}).then(() => {
const index = this.announcements.findIndex((a) => a.id === id)
return window.vuex.state.api.backendInteractor
.dismissAnnouncement({ id })
.then(() => {
const index = this.announcements.findIndex((a) => a.id === id)
if (index < 0) {
return
}
if (index < 0) {
return
}
this.announcements[index].read = true
})
this.announcements[index].read = true
})
},
startFetchingAnnouncements() {
if (this.fetchAnnouncementsTimer) {
@ -123,35 +105,25 @@ export const useAnnouncementsStore = defineStore('announcements', {
clearInterval(interval)
},
postAnnouncement({ content, startsAt, endsAt, allDay }) {
return postAnnouncement({
credentials: useOAuthStore().token,
content,
startsAt,
endsAt,
allDay,
}).then(() => {
return this.fetchAnnouncements()
})
return window.vuex.state.api.backendInteractor
.postAnnouncement({ content, startsAt, endsAt, allDay })
.then(() => {
return this.fetchAnnouncements()
})
},
editAnnouncement({ id, content, startsAt, endsAt, allDay }) {
return editAnnouncement({
id,
content,
startsAt,
endsAt,
allDay,
credentials: useOAuthStore().token,
}).then(() => {
return this.fetchAnnouncements()
})
return window.vuex.state.api.backendInteractor
.editAnnouncement({ id, content, startsAt, endsAt, allDay })
.then(() => {
return this.fetchAnnouncements()
})
},
deleteAnnouncement(id) {
return deleteAnnouncement({
id,
credentials: useOAuthStore().token,
}).then(() => {
return this.fetchAnnouncements()
})
return window.vuex.state.api.backendInteractor
.deleteAnnouncement({ id })
.then(() => {
return this.fetchAnnouncements()
})
},
},
})

View file

@ -1,16 +1,6 @@
import { find, remove } from 'lodash'
import { defineStore } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
createBookmarkFolder,
deleteBookmarkFolder,
fetchBookmarkFolders,
updateBookmarkFolder,
} from 'src/services/api/api.service.js'
import { promiseInterval } from 'src/services/promise_interval/promise_interval.js'
export const useBookmarkFoldersStore = defineStore('bookmarkFolders', {
state: () => ({
allFolders: [],
@ -26,23 +16,6 @@ export const useBookmarkFoldersStore = defineStore('bookmarkFolders', {
},
},
actions: {
startFetching() {
promiseInterval(() => {
this.fetcher = fetchBookmarkFolders({
credentials: useOAuthStore().token,
})
.then(
(folders) => this.setBookmarkFolders(folders),
(rej) => console.error(rej),
)
.catch((e) => {
console.error(e)
})
}, 240000)
},
stopFetching() {
this.fetcher?.stop()
},
setBookmarkFolders(value) {
this.allFolders = value
},
@ -57,31 +30,23 @@ export const useBookmarkFoldersStore = defineStore('bookmarkFolders', {
}
},
createBookmarkFolder({ name, emoji }) {
return createBookmarkFolder({
name,
emoji,
credentials: useOAuthStore().token,
}).then((folder) => {
this.setBookmarkFolder(folder)
return folder
})
return window.vuex.state.api.backendInteractor
.createBookmarkFolder({ name, emoji })
.then((folder) => {
this.setBookmarkFolder(folder)
return folder
})
},
updateBookmarkFolder({ folderId, name, emoji }) {
return updateBookmarkFolder({
credentials: useOAuthStore().token,
folderId,
name,
emoji,
}).then((folder) => {
this.setBookmarkFolder(folder)
return folder
})
return window.vuex.state.api.backendInteractor
.updateBookmarkFolder({ folderId, name, emoji })
.then((folder) => {
this.setBookmarkFolder(folder)
return folder
})
},
deleteBookmarkFolder({ folderId }) {
deleteBookmarkFolder({
folderId,
credentials: useOAuthStore().token,
})
window.vuex.state.api.backendInteractor.deleteBookmarkFolder({ folderId })
remove(this.allFolders, (folder) => folder.id === folderId)
},
},

View file

@ -2,10 +2,8 @@ import { merge } from 'lodash'
import { defineStore } from 'pinia'
import { useInstanceStore } from 'src/stores/instance.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { ensureFinalFallback } from 'src/i18n/languages.js'
import { listEmojiPacks } from 'src/services/api/api.service.js'
import { annotationsLoader } from 'virtual:pleroma-fe/emoji-annotations'
@ -185,14 +183,13 @@ export const useEmojiStore = defineStore('emoji', {
async getAdminPacksLocal(refresh) {
if (!refresh && this.adminPacksLocal) return this.adminPacksLocal
const backendInteractor = window.vuex.state.api.backendInteractor
const listFunction = backendInteractor.listEmojiPacks
this.adminPacksLocalLoading = true
this.adminPacksLocal = await this.getAdminPacks(
useInstanceStore().server,
(params) =>
listEmojiPacks({
...params,
credentials: useOAuthStore().token,
}),
listFunction,
)
this.adminPacksLocalLoading = false
},
@ -209,6 +206,7 @@ export const useEmojiStore = defineStore('emoji', {
page: 1,
pageSize: 0,
})
.then((data) => data.json())
.then((data) => {
if (data.error !== undefined) {
return Promise.reject(data.error)
@ -222,13 +220,15 @@ export const useEmojiStore = defineStore('emoji', {
instance,
page: i,
pageSize,
}).then((pageData) => {
if (pageData.error !== undefined) {
return Promise.reject(pageData.error)
}
})
.then((data) => data.json())
.then((pageData) => {
if (pageData.error !== undefined) {
return Promise.reject(pageData.error)
}
return pageData.packs
}),
return pageData.packs
}),
)
}
@ -247,7 +247,7 @@ export const useEmojiStore = defineStore('emoji', {
}, {})
})
.catch((data) => {
console.error(data)
this.displayError(data)
})
},

View file

@ -11,7 +11,7 @@ import {
LOCAL_DEFAULT_CONFIG_DEFINITIONS,
validateSetting,
} from '../modules/default_config_state.js'
import { fetchKnownDomains } from '../services/api/api.service.js'
import apiService from '../services/api/api.service.js'
import { useInterfaceStore } from 'src/stores/interface.js'
@ -210,7 +210,7 @@ export const useInstanceStore = defineStore('instance', {
},
async getKnownDomains() {
try {
this.knownDomains = await fetchKnownDomains({
this.knownDomains = await apiService.fetchKnownDomains({
credentials: window.vuex.state.users.currentUser.credentials,
})
} catch (e) {

View file

@ -1,23 +1,8 @@
import { find, remove } from 'lodash'
import { defineStore } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
addAccountsToList,
createList,
deleteList,
fetchLists,
getList,
getListAccounts,
removeAccountsFromList,
updateList,
} from 'src/services/api/api.service.js'
import { promiseInterval } from 'src/services/promise_interval/promise_interval.js'
export const useListsStore = defineStore('lists', {
state: () => ({
fetcher: null,
allLists: [],
allListsObject: {},
}),
@ -33,58 +18,34 @@ export const useListsStore = defineStore('lists', {
},
},
actions: {
startFetching() {
promiseInterval(() => {
this.fetcher = fetchLists({
credentials: useOAuthStore().token,
})
.then(
(lists) => this.setLists(lists),
(rej) => console.error(rej),
)
.catch((e) => {
console.error(e)
})
}, 240000)
},
stopFetching() {
this.fetcher?.stop()
},
setLists(value) {
this.allLists = value
},
createList({ title }) {
return createList({
title,
credentials: useOAuthStore().token,
}).then((list) => {
this.setList({ listId: list.id, title })
return list
})
return window.vuex.state.api.backendInteractor
.createList({ title })
.then((list) => {
this.setList({ listId: list.id, title })
return list
})
},
fetchList({ listId }) {
return getList({
listId,
credentials: useOAuthStore().token,
}).then((list) => this.setList({ listId: list.id, title: list.title }))
return window.vuex.state.api.backendInteractor
.getList({ listId })
.then((list) => this.setList({ listId: list.id, title: list.title }))
},
fetchListAccounts({ listId }) {
return getListAccounts({
listId,
credentials: useOAuthStore().token,
}).then((accountIds) => {
if (!this.allListsObject[listId]) {
this.allListsObject[listId] = { accountIds: [] }
}
this.allListsObject[listId].accountIds = accountIds
})
return window.vuex.state.api.backendInteractor
.getListAccounts({ listId })
.then((accountIds) => {
if (!this.allListsObject[listId]) {
this.allListsObject[listId] = { accountIds: [] }
}
this.allListsObject[listId].accountIds = accountIds
})
},
setList({ listId, title }) {
updateList({
listId,
title,
credentials: useOAuthStore().token,
})
window.vuex.state.api.backendInteractor.updateList({ listId, title })
if (!this.allListsObject[listId]) {
this.allListsObject[listId] = { accountIds: [] }
@ -107,55 +68,46 @@ export const useListsStore = defineStore('lists', {
}
this.allListsObject[listId].accountIds = accountIds
if (added.length > 0) {
addAccountsToList({
window.vuex.state.api.backendInteractor.addAccountsToList({
listId,
accountIds: added,
credentials: useOAuthStore().token,
})
}
if (removed.length > 0) {
removeAccountsFromList({
window.vuex.state.api.backendInteractor.removeAccountsFromList({
listId,
accountIds: removed,
credentials: useOAuthStore().token,
})
}
},
addListAccount({ listId, accountId }) {
return addAccountsToList({
listId,
accountIds: [accountId],
credentials: useOAuthStore().token,
}).then((result) => {
if (!this.allListsObject[listId]) {
this.allListsObject[listId] = { accountIds: [] }
}
this.allListsObject[listId].accountIds.push(accountId)
return result
})
return window.vuex.state.api.backendInteractor
.addAccountsToList({ listId, accountIds: [accountId] })
.then((result) => {
if (!this.allListsObject[listId]) {
this.allListsObject[listId] = { accountIds: [] }
}
this.allListsObject[listId].accountIds.push(accountId)
return result
})
},
removeListAccount({ listId, accountId }) {
return removeAccountsFromList({
listId,
accountIds: [accountId],
credentials: useOAuthStore().token,
}).then((result) => {
if (!this.allListsObject[listId]) {
this.allListsObject[listId] = { accountIds: [] }
}
const { accountIds } = this.allListsObject[listId]
const set = new Set(accountIds)
set.delete(accountId)
this.allListsObject[listId].accountIds = [...set]
return window.vuex.state.api.backendInteractor
.removeAccountsFromList({ listId, accountIds: [accountId] })
.then((result) => {
if (!this.allListsObject[listId]) {
this.allListsObject[listId] = { accountIds: [] }
}
const { accountIds } = this.allListsObject[listId]
const set = new Set(accountIds)
set.delete(accountId)
this.allListsObject[listId].accountIds = [...set]
return result
})
return result
})
},
deleteList({ listId }) {
deleteList({
listId,
credentials: useOAuthStore().token,
})
window.vuex.state.api.backendInteractor.deleteList({ listId })
delete this.allListsObject[listId]
remove(this.allLists, (list) => list.id === listId)

View file

@ -41,9 +41,12 @@ export const useOAuthStore = defineStore('oauth', {
userToken: false,
}),
getters: {
token() {
getToken() {
return this.userToken || this.appToken
},
getUserToken() {
return this.userToken
},
},
actions: {
setClientData({ clientId, clientSecret }) {

View file

@ -1,33 +1,25 @@
import { defineStore } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import {
fetchOAuthTokens,
revokeOAuthToken,
} from 'src/services/api/api.service.js'
export const useOAuthTokensStore = defineStore('oauthTokens', {
state: () => ({
tokens: [],
}),
actions: {
fetchTokens() {
fetchOAuthTokens({
credentials: useOAuthStore().token,
}).then((tokens) => {
this.swapTokens(tokens)
})
window.vuex.state.api.backendInteractor
.fetchOAuthTokens()
.then((tokens) => {
this.swapTokens(tokens)
})
},
revokeToken(id) {
revokeOAuthToken({
id,
credentials: useOAuthStore().token,
}).then((response) => {
if (response.status === 201) {
this.swapTokens(this.tokens.filter((token) => token.id !== id))
}
})
window.vuex.state.api.backendInteractor
.revokeOAuthToken({ id })
.then((response) => {
if (response.status === 201) {
this.swapTokens(this.tokens.filter((token) => token.id !== id))
}
})
},
swapTokens(tokens) {
this.tokens = tokens

View file

@ -1,10 +1,6 @@
import { merge } from 'lodash'
import { defineStore } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import { fetchPoll, vote } from 'src/services/api/api.service.js'
export const usePollsStore = defineStore('polls', {
state: () => ({
// Contains key = id, value = number of trackers for this poll
@ -23,17 +19,16 @@ export const usePollsStore = defineStore('polls', {
}
},
updateTrackedPoll(pollId) {
fetchPoll({
pollId,
credentials: useOAuthStore().token,
}).then((poll) => {
setTimeout(() => {
if (this.trackedPolls[pollId]) {
this.updateTrackedPoll(pollId)
}
}, 30 * 1000)
this.mergeOrAddPoll(poll)
})
window.vuex.state.api.backendInteractor
.fetchPoll({ pollId })
.then((poll) => {
setTimeout(() => {
if (this.trackedPolls[pollId]) {
this.updateTrackedPoll(pollId)
}
}, 30 * 1000)
this.mergeOrAddPoll(poll)
})
},
trackPoll(pollId) {
if (!this.trackedPolls[pollId]) {
@ -55,14 +50,12 @@ export const usePollsStore = defineStore('polls', {
}
},
votePoll({ pollId, choices }) {
return vote({
pollId,
choices,
credentials: useOAuthStore().token,
}).then((poll) => {
this.mergeOrAddPoll(poll)
return poll
})
return window.vuex.state.api.backendInteractor
.vote({ pollId, choices })
.then((poll) => {
this.mergeOrAddPoll(poll)
return poll
})
},
},
})

View file

@ -2,9 +2,6 @@ import { filter } from 'lodash'
import { defineStore } from 'pinia'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { setReportState } from 'src/services/api/admin.js'
export const useReportsStore = defineStore('reports', {
state: () => ({
@ -41,21 +38,18 @@ export const useReportsStore = defineStore('reports', {
setReportState({ id, state }) {
const oldState = this.reports[id].state
this.reports[id].state = state
setReportState({
id,
state,
credentials: useOAuthStore().token,
}).catch((e) => {
console.error('Failed to set report state', e)
useInterfaceStore().pushGlobalNotice({
level: 'error',
messageKey: 'general.generic_error_message',
messageArgs: [e.message],
timeout: 5000,
window.vuex.state.api.backendInteractor
.setReportState({ id, state })
.catch((e) => {
console.error('Failed to set report state', e)
useInterfaceStore().pushGlobalNotice({
level: 'error',
messageKey: 'general.generic_error_message',
messageArgs: [e.message],
timeout: 5000,
})
this.reports[id].state = oldState
})
this.reports[id].state = oldState
})
},
addReport(report) {
this.reports[report.id] = report

View file

@ -22,7 +22,6 @@ import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/updat
import { useInstanceStore } from 'src/stores/instance.js'
import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { storage } from 'src/lib/storage.js'
import {
@ -32,7 +31,6 @@ import {
validateSetting,
} from 'src/modules/default_config_state.js'
import { oldDefaultConfigSync } from 'src/modules/old_default_config_state.js'
import { updateProfileJSON } from 'src/services/api/api.service.js'
export const VERSION = 2
export const NEW_USER_DATE = new Date('2026-03-16') // date of writing this, basically
@ -791,10 +789,7 @@ export const useSyncConfigStore = defineStore('sync_config', {
if (!needPush) return
this.updateCache({ username: window.vuex.state.users.currentUser.fqn })
const params = { pleroma_settings_store: { 'pleroma-fe': this.cache } }
updateProfileJSON({
params,
credentials: useOAuthStore().token,
})
window.vuex.state.api.backendInteractor.updateProfileJSON({ params })
},
},
persist: {

View file

@ -14,10 +14,7 @@ import {
import { defineStore } from 'pinia'
import { toRaw } from 'vue'
import { useOAuthStore } from 'src/stores/oauth.js'
import { storage } from 'src/lib/storage.js'
import { updateProfileJSON } from 'src/services/api/api.service.js'
export const NEW_USER_DATE = new Date('2022-08-04') // date of writing this, basically
@ -347,13 +344,12 @@ export const useUserHighlightStore = defineStore('user_highlight', {
const params = {
pleroma_settings_store: { user_highlight: this.cache },
}
updateProfileJSON({
params,
credentials: useOAuthStore().token,
}).then((user) => {
this.initUserHighlight(user)
this.dirty = false
})
window.vuex.state.api.backendInteractor
.updateProfileJSON({ params })
.then((user) => {
this.initUserHighlight(user)
this.dirty = false
})
},
},
persist: {

View file

@ -4,6 +4,7 @@ import { createStore } from 'vuex'
import UserProfile from 'src/components/user_profile/user_profile.vue'
import { getters } from 'src/modules/users.js'
import backendInteractorService from 'src/services/backend_interactor_service/backend_interactor_service.js'
const mutations = {
clearTimeline: () => {
@ -52,6 +53,10 @@ const externalProfileStore = createStore({
actions,
getters: testGetters,
state: {
api: {
fetchers: {},
backendInteractor: backendInteractorService(''),
},
interface: {
browserSupport: '',
},
@ -111,6 +116,10 @@ const localProfileStore = createStore({
actions,
getters: testGetters,
state: {
api: {
fetchers: {},
backendInteractor: backendInteractorService(''),
},
interface: {
browserSupport: '',
},