Merge pull request 'Vite 8 + cleanup for static/dynamic imports' (#3500) from optimize into develop

Reviewed-on: https://git.pleroma.social/pleroma/pleroma-fe/pulls/3500
This commit is contained in:
HJ 2026-06-07 21:40:35 +00:00
commit e239fce8cf
153 changed files with 2235 additions and 955 deletions

View file

@ -1,7 +1,7 @@
# This file is a template, and might need editing before it works on your project.
# Official framework image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/node/tags/
image: node:18
image: node:20
stages:
- check-changelog

View file

@ -1 +1 @@
18.20.8
20.19.0

View file

@ -16,7 +16,7 @@ labels:
steps:
build:
image: docker.io/node:18-alpine
image: docker.io/node:20-alpine
commands:
- apk add --no-cache zip git
- yarn --frozen-lockfile

View file

@ -9,7 +9,7 @@ when:
steps:
install-depends:
image: &node-image
docker.io/node:18-alpine
docker.io/node:20-alpine
commands:
- yarn --frozen-lockfile

View file

@ -1,7 +1,7 @@
import { readFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import * as esbuild from 'esbuild'
import { exactRegex } from '@rolldown/pluginutils'
import { build } from 'vite'
import {
@ -15,106 +15,6 @@ const getSWMessagesAsText = async () => {
}
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)))
const swEnvName = 'virtual:pleroma-fe/service_worker_env'
const swEnvNameResolved = '\0' + swEnvName
const getDevSwEnv = () => `self.serviceWorkerOption = { assets: [] };`
const getProdSwEnv = ({ assets }) =>
`self.serviceWorkerOption = { assets: ${JSON.stringify(assets)} };`
export const devSwPlugin = ({ swSrc, swDest, transformSW, alias }) => {
const swFullSrc = resolve(projectRoot, swSrc)
const esbuildAlias = {}
Object.entries(alias).forEach(([source, dest]) => {
esbuildAlias[source] = dest.startsWith('/') ? projectRoot + dest : dest
})
return {
name: 'dev-sw-plugin',
apply: 'serve',
configResolved() {
/* no-op */
},
resolveId(id) {
const name = id.startsWith('/') ? id.slice(1) : id
if (name === swDest) {
return swFullSrc
} else if (name === swEnvName) {
return swEnvNameResolved
}
return null
},
async load(id) {
if (id === swFullSrc) {
return readFile(swFullSrc, 'utf-8')
} else if (id === swEnvNameResolved) {
return getDevSwEnv()
}
return null
},
/**
* vite does not bundle the service worker
* during dev, and firefox does not support ESM as service worker
* https://bugzilla.mozilla.org/show_bug.cgi?id=1360870
*/
async transform(code, id) {
if (id === swFullSrc && transformSW) {
const res = await esbuild.build({
entryPoints: [swSrc],
bundle: true,
write: false,
outfile: 'sw-pleroma.js',
alias: esbuildAlias,
plugins: [
{
name: 'vite-like-root-resolve',
setup(b) {
b.onResolve({ filter: new RegExp(/^\//) }, (args) => ({
path: resolve(projectRoot, args.path.slice(1)),
}))
},
},
{
name: 'sw-messages',
setup(b) {
b.onResolve(
{ filter: new RegExp('^' + swMessagesName + '$') },
(args) => ({
path: args.path,
namespace: 'sw-messages',
}),
)
b.onLoad(
{ filter: /.*/, namespace: 'sw-messages' },
async () => ({
contents: await getSWMessagesAsText(),
}),
)
},
},
{
name: 'sw-env',
setup(b) {
b.onResolve(
{ filter: new RegExp('^' + swEnvName + '$') },
(args) => ({
path: args.path,
namespace: 'sw-env',
}),
)
b.onLoad({ filter: /.*/, namespace: 'sw-env' }, () => ({
contents: getDevSwEnv(),
}))
},
},
],
})
const text = res.outputFiles[0].text
return text
}
},
}
}
// Idea taken from
// https://github.com/vite-pwa/vite-plugin-pwa/blob/main/src/plugins/build.ts
// rollup does not support compiling to iife if we want to code-split;
@ -122,12 +22,17 @@ export const devSwPlugin = ({ swSrc, swDest, transformSW, alias }) => {
// Run another vite build just for the service worker targeting iife at
// the end of the build.
export const buildSwPlugin = ({ swSrc, swDest }) => {
const swFullSrc = resolve(projectRoot, swSrc)
const swEnvName = 'virtual:pleroma-fe/service_worker_env'
const swEnvNameResolved = '\0' + swEnvName
let config
return {
name: 'build-sw-plugin',
enforce: 'post',
apply: 'build',
configResolved(resolvedConfig) {
resolvedConfig
config = {
define: resolvedConfig.define,
resolve: resolvedConfig.resolve,
@ -135,15 +40,16 @@ export const buildSwPlugin = ({ swSrc, swDest }) => {
publicDir: false,
build: {
...resolvedConfig.build,
lib: {
entry: swSrc,
formats: ['iife'],
name: 'sw_pleroma',
},
emptyOutDir: false,
rollupOptions: {
rolldownOptions: {
input: {
main: swSrc,
},
context: 'self',
output: {
entryFileNames: swDest,
codeSplitting: false,
format: 'iife',
},
},
},
@ -157,27 +63,54 @@ export const buildSwPlugin = ({ swSrc, swDest }) => {
const assets = Object.keys(bundle)
.filter((name) => !/\.map$/.test(name))
.map((name) => '/' + name)
config.plugins.push({
name: 'build-sw-env-plugin',
resolveId(id) {
if (id === swEnvName) {
return swEnvNameResolved
}
return null
mode: 'production',
resolveId: {
filter: { id: exactRegex(swEnvName) },
handler: () => swEnvNameResolved,
},
load(id) {
if (id === swEnvNameResolved) {
return getProdSwEnv({ assets })
}
return null
load: {
filter: { id: exactRegex(swEnvNameResolved) },
handler() {
return `self.serviceWorkerOption = { assets: ${JSON.stringify(assets)} };`
},
},
})
},
},
resolveId: {
filter: { id: new RegExp(swDest) },
handler() {
return swFullSrc
},
},
load: {
filter: { id: new RegExp(swFullSrc) },
async handler() {
config.plugins.push({
name: 'dummy-sw-env',
mode: 'development',
resolveId: {
filter: { id: exactRegex(swEnvName) },
handler: () => swEnvNameResolved,
},
load: {
filter: { id: exactRegex(swEnvNameResolved) },
handler: () => 'self.serviceWorkerOption = { assets: [] }',
},
})
const swBundle = await build(config)
return swBundle.output[0]
},
},
closeBundle: {
order: 'post',
sequential: true,
async handler() {
if (process.env.VITEST) return
console.info('Building service worker for production')
await build(config)
},

1
changelog.d/fast.change Normal file
View file

@ -0,0 +1 @@
Migrated to Vite 8 and optimized our imports, more stuff is loaded on-demand, reducing the initial load time and transfer size

View file

@ -43,7 +43,7 @@
"localforage": "1.10.0",
"parse-link-header": "2.0.0",
"phoenix": "1.8.1",
"pinia": "^3.0.0",
"pinia": "^3.0.4",
"punycode.js": "2.3.1",
"qrcode": "1.5.4",
"querystring-es3": "0.2.1",
@ -65,8 +65,9 @@
"@biomejs/biome": "2.3.11",
"@pinia/testing": "1.0.3",
"@ungap/event-target": "0.2.4",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"@vitejs/devtools": "^0.3.1",
"@vitejs/plugin-vue": "^6.0.7",
"@vitejs/plugin-vue-jsx": "^5.1.5",
"@vitest/browser": "^3.0.7",
"@vitest/ui": "^3.0.7",
"@vue/babel-helper-vue-jsx-merge-props": "1.4.0",
@ -96,11 +97,12 @@
"lodash": "4.17.21",
"msw": "2.10.5",
"nightwatch": "3.12.2",
"oxc": "^1.0.1",
"playwright": "1.57.0",
"postcss": "8.5.6",
"postcss-html": "^1.5.0",
"postcss-scss": "^4.0.6",
"sass": "1.93.2",
"sass-embedded": "^1.100.0",
"selenium-server": "3.141.59",
"semver": "7.7.3",
"serve-static": "2.2.0",
@ -113,9 +115,9 @@
"stylelint-config-recommended-scss": "^14.0.0",
"stylelint-config-recommended-vue": "^1.6.0",
"stylelint-config-standard": "38.0.0",
"vite": "^6.1.0",
"vite-plugin-eslint2": "^5.0.3",
"vite-plugin-stylelint": "^6.0.0",
"vite": "^8.0.0",
"vite-plugin-eslint2": "^5.1.0",
"vite-plugin-stylelint": "^6.1.0",
"vitest": "^3.0.7",
"vue-eslint-parser": "10.2.0"
},

View file

@ -2,22 +2,14 @@ import { throttle } from 'lodash'
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import DesktopNav from './components/desktop_nav/desktop_nav.vue'
import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
import FeaturesPanel from './components/features_panel/features_panel.vue'
import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue'
import MediaModal from './components/media_modal/media_modal.vue'
import MobileNav from './components/mobile_nav/mobile_nav.vue'
import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue'
import NavPanel from './components/nav_panel/nav_panel.vue'
import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
import ShoutPanel from './components/shout_panel/shout_panel.vue'
import SideDrawer from './components/side_drawer/side_drawer.vue'
import StatusHistoryModal from './components/status_history_modal/status_history_modal.vue'
import UserPanel from './components/user_panel/user_panel.vue'
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
import DesktopNav from 'src/components/desktop_nav/desktop_nav.vue'
import FeaturesPanel from 'src/components/features_panel/features_panel.vue'
import GlobalNoticeList from 'src/components/global_notice_list/global_notice_list.vue'
import InstanceSpecificPanel from 'src/components/instance_specific_panel/instance_specific_panel.vue'
import MobileNav from 'src/components/mobile_nav/mobile_nav.vue'
import MobilePostStatusButton from 'src/components/mobile_post_status_button/mobile_post_status_button.vue'
import NavPanel from 'src/components/nav_panel/nav_panel.vue'
import UserPanel from 'src/components/user_panel/user_panel.vue'
import { getOrCreateServiceWorker } from './services/sw/sw'
import { windowHeight, windowWidth } from './services/window_utils/window_utils'
@ -41,27 +33,44 @@ export default {
UserPanel,
NavPanel,
Notifications: defineAsyncComponent(
() => import('./components/notifications/notifications.vue'),
() => import('src/components/notifications/notifications.vue'),
),
InstanceSpecificPanel,
FeaturesPanel,
WhoToFollowPanel,
ShoutPanel,
MediaModal,
SideDrawer,
WhoToFollowPanel: defineAsyncComponent(
() =>
import('src/components/who_to_follow_panel/who_to_follow_panel.vue'),
),
ShoutPanel: defineAsyncComponent(
() => import('src/components/shout_panel/shout_panel.vue'),
),
MediaModal: defineAsyncComponent(
() => import('src/components/media_modal/media_modal.vue'),
),
MobilePostStatusButton,
MobileNav,
DesktopNav,
SettingsModal: defineAsyncComponent(
() => import('./components/settings_modal/settings_modal.vue'),
() => import('src/components/settings_modal/settings_modal.vue'),
),
UpdateNotification: defineAsyncComponent(
() => import('./components/update_notification/update_notification.vue'),
() =>
import('src/components/update_notification/update_notification.vue'),
),
PostStatusModal: defineAsyncComponent(
() => import('src/components/post_status_modal/post_status_modal.vue'),
),
UserReportingModal: defineAsyncComponent(
() =>
import('src/components/user_reporting_modal/user_reporting_modal.vue'),
),
EditStatusModal: defineAsyncComponent(
() => import('src/components/edit_status_modal/edit_status_modal.vue'),
),
StatusHistoryModal: defineAsyncComponent(
() =>
import('src/components/status_history_modal/status_history_modal.vue'),
),
UserReportingModal,
PostStatusModal,
EditStatusModal,
StatusHistoryModal,
GlobalNoticeList,
},
data: () => ({

View file

@ -6,6 +6,10 @@ import { createRouter, createWebHistory } from 'vue-router'
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import Status from 'src/components/status/status.vue'
import StillImage from 'src/components/still-image/still-image.vue'
import { config } from '@fortawesome/fontawesome-svg-core'
import {
FontAwesomeIcon,
@ -611,6 +615,9 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
app.component('FAIcon', FontAwesomeIcon)
app.component('FALayers', FontAwesomeLayers)
app.component('Status', Status)
app.component('RichContent', RichContent)
app.component('StillImage', StillImage)
// remove after vue 3.3
app.config.unwrapInjectedRef = true

View file

@ -1,36 +1,16 @@
import About from 'components/about/about.vue'
import AnnouncementsPage from 'components/announcements_page/announcements_page.vue'
import AuthForm from 'components/auth_form/auth_form.js'
import BookmarkTimeline from 'components/bookmark_timeline/bookmark_timeline.vue'
import BubbleTimeline from 'components/bubble_timeline/bubble_timeline.vue'
import Chat from 'components/chat/chat.vue'
import ChatList from 'components/chat_list/chat_list.vue'
import ConversationPage from 'components/conversation-page/conversation-page.vue'
import DMs from 'components/dm_timeline/dm_timeline.vue'
import Drafts from 'components/drafts/drafts.vue'
import FollowRequests from 'components/follow_requests/follow_requests.vue'
import FriendsTimeline from 'components/friends_timeline/friends_timeline.vue'
import Interactions from 'components/interactions/interactions.vue'
import Lists from 'components/lists/lists.vue'
import ListsEdit from 'components/lists_edit/lists_edit.vue'
import ListsTimeline from 'components/lists_timeline/lists_timeline.vue'
import Notifications from 'components/notifications/notifications.vue'
import OAuthCallback from 'components/oauth_callback/oauth_callback.vue'
import PasswordReset from 'components/password_reset/password_reset.vue'
import PublicAndExternalTimeline from 'components/public_and_external_timeline/public_and_external_timeline.vue'
import PublicTimeline from 'components/public_timeline/public_timeline.vue'
import Registration from 'components/registration/registration.vue'
import RemoteUserResolver from 'components/remote_user_resolver/remote_user_resolver.vue'
import Search from 'components/search/search.vue'
import ShoutPanel from 'components/shout_panel/shout_panel.vue'
import TagTimeline from 'components/tag_timeline/tag_timeline.vue'
import UserProfile from 'components/user_profile/user_profile.vue'
import WhoToFollow from 'components/who_to_follow/who_to_follow.vue'
import { defineAsyncComponent } from 'vue'
import BookmarkTimeline from 'src/components/bookmark_timeline/bookmark_timeline.vue'
import BubbleTimeline from 'src/components/bubble_timeline/bubble_timeline.vue'
import ConversationPage from 'src/components/conversation-page/conversation-page.vue'
import DMs from 'src/components/dm_timeline/dm_timeline.vue'
import FriendsTimeline from 'src/components/friends_timeline/friends_timeline.vue'
import NavPanel from 'src/components/nav_panel/nav_panel.vue'
import BookmarkFolderEdit from '../components/bookmark_folder_edit/bookmark_folder_edit.vue'
import BookmarkFolders from '../components/bookmark_folders/bookmark_folders.vue'
import QuotesTimeline from '../components/quotes_timeline/quotes_timeline.vue'
import PublicAndExternalTimeline from 'src/components/public_and_external_timeline/public_and_external_timeline.vue'
import PublicTimeline from 'src/components/public_timeline/public_timeline.vue'
import QuotesTimeline from 'src/components/quotes_timeline/quotes_timeline.vue'
import RemoteUserResolver from 'src/components/remote_user_resolver/remote_user_resolver.vue'
import TagTimeline from 'src/components/tag_timeline/tag_timeline.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
@ -100,12 +80,16 @@ export default (store) => {
{
name: 'external-user-profile',
path: '/users/$:id',
component: UserProfile,
component: defineAsyncComponent(
() => import('src/components/user_profile/user_profile.vue'),
),
},
{
name: 'interactions',
path: '/users/:username/interactions',
component: Interactions,
component: defineAsyncComponent(
() => import('src/components/interactions/interactions.vue'),
),
beforeEnter: validateAuthenticatedRoute,
},
{
@ -114,69 +98,148 @@ export default (store) => {
component: DMs,
beforeEnter: validateAuthenticatedRoute,
},
{ name: 'registration', path: '/registration', component: Registration },
{
name: 'registration',
path: '/registration',
component: defineAsyncComponent(
() => import('src/components/registration/registration.vue'),
),
},
{
name: 'password-reset',
path: '/password-reset',
component: PasswordReset,
component: defineAsyncComponent(
() => import('src/components/password_reset/password_reset.vue'),
),
props: true,
},
{
name: 'registration-token',
path: '/registration/:token',
component: Registration,
component: defineAsyncComponent(
() => import('src/components/registration/registration.vue'),
),
},
{
name: 'friend-requests',
path: '/friend-requests',
component: FollowRequests,
component: defineAsyncComponent(
() => import('src/components/follow_requests/follow_requests.vue'),
),
beforeEnter: validateAuthenticatedRoute,
},
{
name: 'notifications',
path: '/:username/notifications',
component: Notifications,
component: defineAsyncComponent(
() => import('src/components/notifications/notifications.vue'),
),
props: () => ({ disableTeleport: true }),
beforeEnter: validateAuthenticatedRoute,
},
{ name: 'login', path: '/login', component: AuthForm },
{
name: 'login',
path: '/login',
component: defineAsyncComponent(
() => import('src/components/auth_form/auth_form.js'),
),
},
{
name: 'shout-panel',
path: '/shout-panel',
component: ShoutPanel,
component: defineAsyncComponent(
() => import('src/components/shout_panel/shout_panel.vue'),
),
props: () => ({ floating: false }),
},
{
name: 'oauth-callback',
path: '/oauth-callback',
component: OAuthCallback,
component: defineAsyncComponent(
() => import('src/components/oauth_callback/oauth_callback.vue'),
),
props: (route) => ({ code: route.query.code }),
},
{
name: 'search',
path: '/search',
component: Search,
component: defineAsyncComponent(
() => import('src/components/search/search.vue'),
),
props: (route) => ({ query: route.query.query }),
},
{
name: 'who-to-follow',
path: '/who-to-follow',
component: WhoToFollow,
component: defineAsyncComponent(
() => import('src/components/who_to_follow/who_to_follow.vue'),
),
beforeEnter: validateAuthenticatedRoute,
},
{ name: 'about', path: '/about', component: About },
{
name: 'about',
path: '/about',
component: defineAsyncComponent(
() => import('src/components/about/about.vue'),
),
},
{
name: 'announcements',
path: '/announcements',
component: AnnouncementsPage,
component: defineAsyncComponent(
() =>
import('src/components/announcements_page/announcements_page.vue'),
),
},
{
name: 'drafts',
path: '/drafts',
component: defineAsyncComponent(
() => import('src/components/drafts/drafts.vue'),
),
},
{
name: 'user-profile',
path: '/users/:name',
component: defineAsyncComponent(
() => import('src/components/user_profile/user_profile.vue'),
),
},
{
name: 'legacy-user-profile',
path: '/:name',
component: defineAsyncComponent(
() => import('src/components/user_profile/user_profile.vue'),
),
},
{
name: 'lists',
path: '/lists',
component: defineAsyncComponent(
() => import('src/components/lists/lists.vue'),
),
},
{
name: 'lists-timeline',
path: '/lists/:id',
component: defineAsyncComponent(
() => import('src/components/lists_timeline/lists_timeline.vue'),
),
},
{
name: 'lists-edit',
path: '/lists/:id/edit',
component: defineAsyncComponent(
() => import('src/components/lists_edit/lists_edit.vue'),
),
},
{
name: 'lists-new',
path: '/lists/new',
component: defineAsyncComponent(
() => import('src/components/lists_edit/lists_edit.vue'),
),
},
{ name: 'drafts', path: '/drafts', component: Drafts },
{ name: 'user-profile', path: '/users/:name', component: UserProfile },
{ name: 'legacy-user-profile', path: '/:name', component: UserProfile },
{ name: 'lists', path: '/lists', component: Lists },
{ name: 'lists-timeline', path: '/lists/:id', component: ListsTimeline },
{ name: 'lists-edit', path: '/lists/:id/edit', component: ListsEdit },
{ name: 'lists-new', path: '/lists/new', component: ListsEdit },
{
name: 'edit-navigation',
path: '/nav-edit',
@ -187,12 +250,19 @@ export default (store) => {
{
name: 'bookmark-folders',
path: '/bookmark_folders',
component: BookmarkFolders,
component: defineAsyncComponent(
() => import('src/components/bookmark_folders/bookmark_folders.vue'),
),
},
{
name: 'bookmark-folder-new',
path: '/bookmarks/new-folder',
component: BookmarkFolderEdit,
component: defineAsyncComponent(
() =>
import(
'src/components/bookmark_folder_edit/bookmark_folder_edit.vue'
),
),
},
{
name: 'bookmark-folder',
@ -202,7 +272,12 @@ export default (store) => {
{
name: 'bookmark-folder-edit',
path: '/bookmarks/:id/edit',
component: BookmarkFolderEdit,
component: defineAsyncComponent(
() =>
import(
'src/components/bookmark_folder_edit/bookmark_folder_edit.vue'
),
),
},
]
@ -211,14 +286,18 @@ export default (store) => {
{
name: 'chat',
path: '/users/:username/chats/:recipient_id',
component: Chat,
component: defineAsyncComponent(
() => import('src/components/chat/chat.vue'),
),
meta: { dontScroll: false },
beforeEnter: validateAuthenticatedRoute,
},
{
name: 'chats',
path: '/users/:username/chats',
component: ChatList,
component: defineAsyncComponent(
() => import('src/components/chat_list/chat_list.vue'),
),
meta: { dontScroll: false },
beforeEnter: validateAuthenticatedRoute,
},

View file

@ -1,10 +1,10 @@
import { mapState } from 'pinia'
import FeaturesPanel from '../features_panel/features_panel.vue'
import InstanceSpecificPanel from '../instance_specific_panel/instance_specific_panel.vue'
import MRFTransparencyPanel from '../mrf_transparency_panel/mrf_transparency_panel.vue'
import StaffPanel from '../staff_panel/staff_panel.vue'
import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
import FeaturesPanel from 'src/components/features_panel/features_panel.vue'
import InstanceSpecificPanel from 'src/components/instance_specific_panel/instance_specific_panel.vue'
import MRFTransparencyPanel from 'src/components/mrf_transparency_panel/mrf_transparency_panel.vue'
import StaffPanel from 'src/components/staff_panel/staff_panel.vue'
import TermsOfServicePanel from 'src/components/terms_of_service_panel/terms_of_service_panel.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'

View file

@ -1,10 +1,9 @@
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import Popover from 'src/components/popover/popover.vue'
import ProgressButton from 'src/components/progress_button/progress_button.vue'
import UserListMenu from 'src/components/user_list_menu/user_list_menu.vue'
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import Popover from '../popover/popover.vue'
import ProgressButton from '../progress_button/progress_button.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -27,8 +26,15 @@ const AccountActions = {
ProgressButton,
Popover,
UserListMenu,
ConfirmModal,
UserTimedFilterModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
UserTimedFilterModal: defineAsyncComponent(
() =>
import(
'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
),
),
},
methods: {
showConfirmRemoveUserFromFollowers() {

View file

@ -94,7 +94,7 @@
</template>
</Popover>
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingConfirmBlock && !blockExpiration"
ref="blockDialog"
:title="$t('user_card.block_confirm_title')"
@ -114,10 +114,10 @@
/>
</template>
</i18n-t>
</confirm-modal>
</ConfirmModal>
</teleport>
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingConfirmRemoveFollower"
:title="$t('user_card.remove_follower_confirm_title')"
:confirm-text="$t('user_card.remove_follower_confirm_accept_button')"
@ -136,7 +136,7 @@
/>
</template>
</i18n-t>
</confirm-modal>
</ConfirmModal>
<UserTimedFilterModal
v-if="blockExpiration"
ref="timedBlockDialog"

View file

@ -1,15 +1,13 @@
import { mapState } from 'vuex'
import AnnouncementEditor from 'src/components/announcement_editor/announcement_editor.vue'
import localeService from '../../services/locale/locale.service.js'
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
import RichContent from '../rich_content/rich_content.jsx'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
const Announcement = {
components: {
AnnouncementEditor,
RichContent,
},
data() {
return {

View file

@ -1,4 +1,4 @@
import Checkbox from '../checkbox/checkbox.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
const AnnouncementEditor = {
components: {

View file

@ -1,7 +1,7 @@
import { mapState } from 'vuex'
import Announcement from '../announcement/announcement.vue'
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
import Announcement from 'src/components/announcement/announcement.vue'
import AnnouncementEditor from 'src/components/announcement_editor/announcement_editor.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'

View file

@ -1,10 +1,9 @@
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import Popover from 'src/components/popover/popover.vue'
import VideoAttachment from 'src/components/video_attachment/video_attachment.vue'
import nsfwImage from '../../assets/nsfw.png'
import Flash from '../flash/flash.vue'
import Popover from '../popover/popover.vue'
import StillImage from '../still-image/still-image.vue'
import VideoAttachment from '../video_attachment/video_attachment.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
@ -69,9 +68,11 @@ const Attachment = {
}
},
components: {
Flash,
StillImage,
VideoAttachment,
Flash: defineAsyncComponent(() => import('src/components/flash/flash.vue')),
VideoAttachment: defineAsyncComponent(
() => import('src/components/video_attachment/video_attachment.vue'),
),
Popover,
},
computed: {

View file

@ -1,9 +1,9 @@
import { mapState } from 'pinia'
import { h, resolveComponent } from 'vue'
import LoginForm from '../login_form/login_form.vue'
import MFARecoveryForm from '../mfa_form/recovery_form.vue'
import MFATOTPForm from '../mfa_form/totp_form.vue'
import LoginForm from 'src/components/login_form/login_form.vue'
import MFARecoveryForm from 'src/components/mfa_form/recovery_form.vue'
import MFATOTPForm from 'src/components/mfa_form/totp_form.vue'
import { useAuthFlowStore } from 'src/stores/auth_flow.js'

View file

@ -1,4 +1,4 @@
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import { useInstanceStore } from 'src/stores/instance.js'

View file

@ -1,7 +1,6 @@
import RichContent from 'src/components/rich_content/rich_content.jsx'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserLink from '../user_link/user_link.vue'
import UserPopover from '../user_popover/user_popover.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserLink from 'src/components/user_link/user_link.vue'
import UserPopover from 'src/components/user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -13,7 +12,7 @@ const BasicUserCard = {
components: {
UserPopover,
UserAvatar,
RichContent,
UserLink,
},
methods: {

View file

@ -1,7 +1,7 @@
import { mapState } from 'pinia'
import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue'
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'

View file

@ -1,5 +1,5 @@
import EmojiPicker from 'src/components/emoji_picker/emoji_picker.vue'
import apiService from '../../services/api/api.service'
import EmojiPicker from '../emoji_picker/emoji_picker.vue'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
import { useInterfaceStore } from 'src/stores/interface.js'

View file

@ -1,4 +1,4 @@
import BookmarkFolderCard from '../bookmark_folder_card/bookmark_folder_card.vue'
import BookmarkFolderCard from 'src/components/bookmark_folder_card/bookmark_folder_card.vue'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const Bookmarks = {
created() {

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const BubbleTimeline = {
components: {

View file

@ -1,14 +1,14 @@
import _ from 'lodash'
import { throttle } from 'lodash'
import { mapState as mapPiniaState } from 'pinia'
import { mapGetters, mapState } from 'vuex'
import ChatMessage from 'src/components/chat_message/chat_message.vue'
import ChatTitle from 'src/components/chat_title/chat_title.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import { WSConnectionStatus } from '../../services/api/api.service.js'
import chatService from '../../services/chat_service/chat_service.js'
import { buildFakeMessage } from '../../services/chat_utils/chat_utils.js'
import { promiseInterval } from '../../services/promise_interval/promise_interval.js'
import ChatMessage from '../chat_message/chat_message.vue'
import ChatTitle from '../chat_title/chat_title.vue'
import PostStatusForm from '../post_status_form/post_status_form.vue'
import {
getNewTopPosition,
getScrollPosition,
@ -224,7 +224,7 @@ const Chat = {
}
}, 5000)
},
handleScroll: _.throttle(function () {
handleScroll: throttle(function () {
this.lastScrollPosition = getScrollPosition()
if (!this.currentChat) {
return

View file

@ -1,8 +1,8 @@
import { mapGetters, mapState } from 'vuex'
import ChatListItem from '../chat_list_item/chat_list_item.vue'
import ChatNew from '../chat_new/chat_new.vue'
import List from '../list/list.vue'
import ChatListItem from 'src/components/chat_list_item/chat_list_item.vue'
import ChatNew from 'src/components/chat_new/chat_new.vue'
import List from 'src/components/list/list.vue'
const ChatList = {
components: {

View file

@ -1,10 +1,10 @@
import { mapState } from 'vuex'
import AvatarList from '../avatar_list/avatar_list.vue'
import ChatTitle from '../chat_title/chat_title.vue'
import StatusBody from '../status_content/status_content.vue'
import Timeago from '../timeago/timeago.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import AvatarList from 'src/components/avatar_list/avatar_list.vue'
import ChatTitle from 'src/components/chat_title/chat_title.vue'
import StatusBody from 'src/components/status_content/status_content.vue'
import Timeago from 'src/components/timeago/timeago.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
const ChatListItem = {
name: 'ChatListItem',

View file

@ -2,13 +2,14 @@ import { mapState as mapPiniaState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import { mapGetters, mapState } from 'vuex'
import Attachment from '../attachment/attachment.vue'
import ChatMessageDate from '../chat_message_date/chat_message_date.vue'
import Gallery from '../gallery/gallery.vue'
import LinkPreview from '../link-preview/link-preview.vue'
import Popover from '../popover/popover.vue'
import StatusContent from '../status_content/status_content.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import Attachment from 'src/components/attachment/attachment.vue'
import ChatMessageDate from 'src/components/chat_message_date/chat_message_date.vue'
import Gallery from 'src/components/gallery/gallery.vue'
import LinkPreview from 'src/components/link-preview/link-preview.vue'
import Popover from 'src/components/popover/popover.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserPopover from 'src/components/user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
@ -37,9 +38,7 @@ const ChatMessage = {
Gallery,
LinkPreview,
ChatMessageDate,
UserPopover: defineAsyncComponent(
() => import('../user_popover/user_popover.vue'),
),
UserPopover,
},
computed: {
// Returns HH:MM (hours and minutes) in local time.

View file

@ -1,7 +1,7 @@
import { mapGetters, mapState } from 'vuex'
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faChevronLeft, faSearch } from '@fortawesome/free-solid-svg-icons'

View file

@ -1,7 +1,7 @@
import { defineAsyncComponent } from 'vue'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserPopover from 'src/components/user_popover/user_popover.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -9,10 +9,8 @@ export default {
name: 'ChatTitle',
components: {
UserAvatar,
RichContent,
UserPopover: defineAsyncComponent(
() => import('../user_popover/user_popover.vue'),
),
UserPopover,
},
props: ['user', 'withAvatar'],
computed: {

View file

@ -66,8 +66,8 @@
<script>
import { throttle } from 'lodash'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import { hex2rgb } from '../../services/color_convert/color_convert.js'
import Checkbox from '../checkbox/checkbox.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEyeDropper } from '@fortawesome/free-solid-svg-icons'

View file

@ -1,4 +1,4 @@
import DialogModal from '../dialog_modal/dialog_modal.vue'
import DialogModal from 'src/components/dialog_modal/dialog_modal.vue'
/**
* This component emits the following events:

View file

@ -1,7 +1,7 @@
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import Select from 'src/components/select/select.vue'
import ConfirmModal from './confirm_modal.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -12,7 +12,10 @@ export default {
showing: false,
}),
components: {
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
Select,
},
computed: {

View file

@ -1,5 +1,5 @@
<template>
<confirm-modal
<ConfirmModal
v-if="showing"
:title="$t('user_card.mute_confirm_title')"
:confirm-text="$t('user_card.mute_confirm_accept_button')"
@ -18,7 +18,7 @@
<span v-text="user.screen_name_ui" />
</template>
</i18n-t>
</confirm-modal>
</ConfirmModal>
</template>
<script src="./mute_confirm.js" />

View file

@ -1,4 +1,4 @@
import Conversation from '../conversation/conversation.vue'
import Conversation from 'src/components/conversation/conversation.vue'
const conversationPage = {
components: {

View file

@ -2,11 +2,10 @@ import { clone, filter, findIndex, get, reduce } from 'lodash'
import { mapState as mapPiniaState } from 'pinia'
import { mapState } from 'vuex'
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
import QuickViewSettings from 'src/components/quick_view_settings/quick_view_settings.vue'
import ThreadTree from 'src/components/thread_tree/thread_tree.vue'
import { WSConnectionStatus } from '../../services/api/api.service.js'
import QuickFilterSettings from '../quick_filter_settings/quick_filter_settings.vue'
import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue'
import Status from '../status/status.vue'
import ThreadTree from '../thread_tree/thread_tree.vue'
import { useInterfaceStore } from 'src/stores/interface'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -402,7 +401,6 @@ const conversation = {
}),
},
components: {
Status,
ThreadTree,
QuickFilterSettings,
QuickViewSettings,

View file

@ -1,7 +1,6 @@
import SearchBar from 'components/search_bar/search_bar.vue'
import { mapActions, mapState } from 'pinia'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { defineAsyncComponent } from 'vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
@ -39,7 +38,9 @@ library.add(
export default {
components: {
SearchBar,
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
},
data: () => ({
searchBarHidden: true,

View file

@ -79,7 +79,7 @@
</div>
</div>
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingConfirmLogout"
:title="$t('login.logout_confirm_title')"
:confirm-danger="true"
@ -89,7 +89,7 @@
@cancelled="hideConfirmLogout"
>
{{ $t('login.logout_confirm') }}
</confirm-modal>
</ConfirmModal>
</teleport>
</nav>
</template>

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const DMs = {
computed: {

View file

@ -1,4 +1,4 @@
import ProgressButton from '../progress_button/progress_button.vue'
import ProgressButton from 'src/components/progress_button/progress_button.vue'
const DomainMuteCard = {
props: ['domain'],

View file

@ -1,7 +1,6 @@
import { cloneDeep } from 'lodash'
import { defineAsyncComponent } from 'vue'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
import EditStatusForm from 'src/components/edit_status_form/edit_status_form.vue'
import Gallery from 'src/components/gallery/gallery.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
@ -16,8 +15,12 @@ library.add(faPollH)
const Draft = {
components: {
PostStatusForm,
EditStatusForm,
ConfirmModal,
EditStatusForm: defineAsyncComponent(
() => import('src/components/edit_status_form/edit_status_form.vue'),
),
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
StatusContent,
Gallery,
},

View file

@ -39,7 +39,7 @@
class="faint"
>{{ $t('drafts.empty') }}</p>
</span>
<gallery
<Gallery
v-if="draft.files?.length !== 0"
class="attachments media-body"
:compact="true"
@ -77,7 +77,7 @@
/>
</div>
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingConfirmDialog"
:title="$t('drafts.abandon_confirm_title')"
:confirm-text="$t('drafts.abandon_confirm_accept_button')"
@ -86,7 +86,7 @@
@cancelled="hideConfirmDialog"
>
{{ $t('drafts.abandon_confirm') }}
</confirm-modal>
</ConfirmModal>
</teleport>
<div class="actions">
<button

View file

@ -1,4 +1,4 @@
import DialogModal from 'src/components/dialog_modal/dialog_modal.vue'
import { defineAsyncComponent } from 'vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -9,7 +9,9 @@ const DraftCloser = {
}
},
components: {
DialogModal,
DialogModal: defineAsyncComponent(
() => import('src/components/dialog_modal/dialog_modal.vue'),
),
},
emits: ['save', 'discard'],
computed: {

View file

@ -1,6 +1,6 @@
<template>
<teleport to="#modal">
<dialog-modal
<DialogModal
v-if="showing"
v-body-scroll-lock="true"
class="confirm-modal"
@ -36,7 +36,7 @@
{{ $t('post_status.close_confirm_continue_composing_button') }}
</button>
</template>
</dialog-modal>
</DialogModal>
</teleport>
</template>

View file

@ -1,4 +1,5 @@
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
import { defineAsyncComponent } from 'vue'
import Draft from 'src/components/draft/draft.vue'
import List from 'src/components/list/list.vue'
@ -6,7 +7,9 @@ const Drafts = {
components: {
Draft,
List,
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
},
data() {
return {

View file

@ -1,5 +1,5 @@
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import statusPosterService from '../../services/status_poster/status_poster.service.js'
import PostStatusForm from '../post_status_form/post_status_form.vue'
const EditStatusForm = {
components: {

View file

@ -1,13 +1,15 @@
import get from 'lodash/get'
import { get } from 'lodash'
import { defineAsyncComponent } from 'vue'
import EditStatusForm from '../edit_status_form/edit_status_form.vue'
import Modal from '../modal/modal.vue'
import Modal from 'src/components/modal/modal.vue'
import { useEditStatusStore } from 'src/stores/editStatus.js'
const EditStatusModal = {
components: {
EditStatusForm,
EditStatusForm: defineAsyncComponent(
() => import('src/components/edit_status_form/edit_status_form.vue'),
),
Modal,
},
data() {

View file

@ -37,7 +37,7 @@
:title="$t('emoji.add_emoji')"
@click.prevent="togglePicker"
>
<FAIcon :icon="['far', 'smile-beam']" />
<FAIcon :icon="['far', 'face-smile-beam']" />
</button>
<EmojiPicker
v-if="enableEmojiPicker"

View file

@ -1,10 +1,9 @@
import { chunk, debounce, trim } from 'lodash'
import { defineAsyncComponent } from 'vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Popover from 'src/components/popover/popover.vue'
import { ensureFinalFallback } from '../../i18n/languages.js'
import Checkbox from '../checkbox/checkbox.vue'
import StillImage from '../still-image/still-image.vue'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
@ -139,10 +138,10 @@ const EmojiPicker = {
},
components: {
StickerPicker: defineAsyncComponent(
() => import('../sticker_picker/sticker_picker.vue'),
() => import('src/components/sticker_picker/sticker_picker.vue'),
),
Checkbox,
StillImage,
Popover,
},
methods: {

View file

@ -49,7 +49,7 @@
v-if="group.image"
class="emoji-picker-header-image"
>
<still-image
<StillImage
:alt="group.text"
:src="group.image"
/>
@ -131,7 +131,7 @@
v-if="!emoji.imageUrl"
class="emoji-picker-emoji -unicode"
>{{ emoji.replacement }}</span>
<still-image
<StillImage
v-else
class="emoji-picker-emoji -custom"
loading="lazy"

View file

@ -1,6 +1,5 @@
import StillImage from 'src/components/still-image/still-image.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserListPopover from '../user_list_popover/user_list_popover.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserListPopover from 'src/components/user_list_popover/user_list_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -17,7 +16,6 @@ const EmojiReactions = {
components: {
UserAvatar,
UserListPopover,
StillImage,
},
props: ['status'],
data: () => ({

View file

@ -1,14 +1,17 @@
import { defineAsyncComponent } from 'vue'
import {
requestFollow,
requestUnfollow,
} from '../../services/follow_manipulate/follow_manipulate'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
export default {
props: ['relationship', 'user', 'labelFollowing', 'buttonClass'],
components: {
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
},
data() {
return {

View file

@ -8,7 +8,7 @@
>
{{ label }}
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingConfirmUnfollow"
:title="$t('user_card.unfollow_confirm_title')"
:confirm-text="$t('user_card.unfollow_confirm_accept_button')"
@ -27,7 +27,7 @@
/>
</template>
</i18n-t>
</confirm-modal>
</ConfirmModal>
</teleport>
</button>
</template>

View file

@ -1,7 +1,7 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import FollowButton from '../follow_button/follow_button.vue'
import RemoteFollow from '../remote_follow/remote_follow.vue'
import RemoveFollowerButton from '../remove_follower_button/remove_follower_button.vue'
import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue'
import FollowButton from 'src/components/follow_button/follow_button.vue'
import RemoteFollow from 'src/components/remote_follow/remote_follow.vue'
import RemoveFollowerButton from 'src/components/remove_follower_button/remove_follower_button.vue'
const FollowCard = {
props: ['user', 'noFollowsYou'],

View file

@ -1,6 +1,7 @@
import { defineAsyncComponent } from 'vue'
import { notificationsFromStore } from '../../services/notification_utils/notification_utils.js'
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -8,7 +9,9 @@ const FollowRequestCard = {
props: ['user'],
components: {
BasicUserCard,
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
},
data() {
return {

View file

@ -15,7 +15,7 @@
</button>
</div>
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingApproveConfirmDialog"
:title="$t('user_card.approve_confirm_title')"
:confirm-text="$t('user_card.approve_confirm_accept_button')"
@ -24,8 +24,8 @@
@cancelled="hideApproveConfirmDialog"
>
{{ $t('user_card.approve_confirm', { user: user.screen_name_ui }) }}
</confirm-modal>
<confirm-modal
</ConfirmModal>
<ConfirmModal
v-if="showingDenyConfirmDialog"
:title="$t('user_card.deny_confirm_title')"
:confirm-text="$t('user_card.deny_confirm_accept_button')"
@ -34,7 +34,7 @@
@cancelled="hideDenyConfirmDialog"
>
{{ $t('user_card.deny_confirm', { user: user.screen_name_ui }) }}
</confirm-modal>
</ConfirmModal>
</teleport>
</basic-user-card>
</template>

View file

@ -1,4 +1,4 @@
import FollowRequestCard from '../follow_request_card/follow_request_card.vue'
import FollowRequestCard from 'src/components/follow_request_card/follow_request_card.vue'
const FollowRequests = {
components: {

View file

@ -1,7 +1,7 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Popover from 'src/components/popover/popover.vue'
import Select from 'src/components/select/select.vue'
import LocalSettingIndicator from 'src/components/settings_modal/helpers/local_setting_indicator.vue'
import Select from '../select/select.vue'
import { useInterfaceStore } from 'src/stores/interface.js'

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const FriendsTimeline = {
components: {

View file

@ -1,6 +1,6 @@
import { set, sumBy } from 'lodash'
import Attachment from '../attachment/attachment.vue'
import Attachment from 'src/components/attachment/attachment.vue'
import { useMediaViewerStore } from 'src/stores/media_viewer.js'

View file

@ -1,5 +1,5 @@
import Notifications from 'src/components/notifications/notifications.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import Notifications from '../notifications/notifications.vue'
const tabModeDict = {
mentions: ['mention'],

View file

@ -1,7 +1,7 @@
import { v4 as uuidv4 } from 'uuid'
import Select from 'src/components/select/select.vue'
import localeService from '../../services/locale/locale.service.js'
import Select from '../select/select.vue'
export default {
components: {

View file

@ -1,4 +1,4 @@
import ListsCard from '../lists_card/lists_card.vue'
import ListsCard from 'src/components/lists_card/lists_card.vue'
import { useListsStore } from 'src/stores/lists.js'

View file

@ -1,11 +1,11 @@
import { mapState as mapPiniaState } from 'pinia'
import { mapGetters, mapState } from 'vuex'
import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue'
import ListsUserSearch from 'src/components/lists_user_search/lists_user_search.vue'
import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import ListsUserSearch from '../lists_user_search/lists_user_search.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useListsStore } from 'src/stores/lists.js'

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
import { useListsStore } from 'src/stores/lists.js'

View file

@ -1,6 +1,6 @@
import { debounce } from 'lodash'
import Checkbox from '../checkbox/checkbox.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faChevronLeft, faSearch } from '@fortawesome/free-solid-svg-icons'

View file

@ -1,10 +1,8 @@
import Flash from 'src/components/flash/flash.vue'
import { defineAsyncComponent } from 'vue'
import Modal from 'src/components/modal/modal.vue'
import StillImage from 'src/components/still-image/still-image.vue'
import GestureService from '../../services/gesture_service/gesture_service'
import Modal from '../modal/modal.vue'
import PinchZoom from '../pinch_zoom/pinch_zoom.vue'
import StillImage from '../still-image/still-image.vue'
import SwipeClick from '../swipe_click/swipe_click.vue'
import VideoAttachment from '../video_attachment/video_attachment.vue'
import { useMediaViewerStore } from 'src/stores/media_viewer.js'
@ -20,12 +18,17 @@ library.add(faChevronLeft, faChevronRight, faCircleNotch, faTimes)
const MediaModal = {
components: {
StillImage,
VideoAttachment,
PinchZoom,
SwipeClick,
VideoAttachment: defineAsyncComponent(
() => import('src/components/video_attachment/video_attachment.vue'),
),
PinchZoom: defineAsyncComponent(
() => import('src/components/pinch_zoom/pinch_zoom.vue'),
),
SwipeClick: defineAsyncComponent(
() => import('src/components/swipe_click/swipe_click.vue'),
),
Modal,
Flash,
Flash: defineAsyncComponent(() => import('src/components/flash/flash.vue')),
},
data() {
return {

View file

@ -2,12 +2,13 @@ import { mapState as mapPiniaState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import { mapGetters, mapState } from 'vuex'
import UnicodeDomainIndicator from 'src/components/unicode_domain_indicator/unicode_domain_indicator.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserPopover from 'src/components/user_popover/user_popover.vue'
import {
highlightClass,
highlightStyle,
} from '../../services/user_highlighter/user_highlighter.js'
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js'
@ -24,9 +25,7 @@ const MentionLink = {
components: {
UserAvatar,
UnicodeDomainIndicator,
UserPopover: defineAsyncComponent(
() => import('../user_popover/user_popover.vue'),
),
UserPopover,
},
props: {
url: {

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const Mentions = {
computed: {

View file

@ -1,4 +1,5 @@
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import { mapGetters } from 'vuex'
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
@ -7,9 +8,6 @@ import {
countExtraNotifications,
unseenNotificationsFromStore,
} from '../../services/notification_utils/notification_utils'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import Notifications from '../notifications/notifications.vue'
import SideDrawer from '../side_drawer/side_drawer.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useInstanceStore } from 'src/stores/instance.js'
@ -29,10 +27,16 @@ library.add(faTimes, faBell, faBars, faArrowUp, faMinus, faCheckDouble)
const MobileNav = {
components: {
SideDrawer,
Notifications,
SideDrawer: defineAsyncComponent(
() => import('src/components/side_drawer/side_drawer.vue'),
),
Notifications: defineAsyncComponent(
() => import('src/components/notifications/notifications.vue'),
),
NavigationPins,
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
},
data: () => ({
notificationsCloseGesture: undefined,
@ -64,6 +68,7 @@ const MobileNav = {
countExtraNotifications(
this.$store,
useMergedConfigStore().mergedConfig,
useAnnouncementsStore().unreadAnnouncementCount,
)
)
},

View file

@ -106,7 +106,7 @@
:logout="logout"
/>
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingConfirmLogout"
:title="$t('login.logout_confirm_title')"
:confirm-danger="true"
@ -116,7 +116,7 @@
@cancelled="hideConfirmLogout"
>
{{ $t('login.logout_confirm') }}
</confirm-modal>
</ConfirmModal>
</teleport>
</div>
</template>

View file

@ -1,5 +1,5 @@
import DialogModal from '../dialog_modal/dialog_modal.vue'
import Popover from '../popover/popover.vue'
import DialogModal from 'src/components/dialog_modal/dialog_modal.vue'
import Popover from 'src/components/popover/popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'

View file

@ -1,5 +1,5 @@
import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue'
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
const MuteCard = {
props: ['userId'],

View file

@ -11,7 +11,6 @@ import {
routeTo,
TIMELINES,
} from 'src/components/navigation/navigation.js'
import StillImage from 'src/components/still-image/still-image.vue'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
@ -54,9 +53,7 @@ const NavPanel = {
return routeTo(item, this.currentUser)
},
},
components: {
StillImage,
},
components: {},
computed: {
getters() {
return this.$store.getters

View file

@ -1,20 +1,17 @@
import { defineAsyncComponent } from 'vue'
import { mapState } from 'vuex'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import Report from 'src/components/report/report.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import Timeago from 'src/components/timeago/timeago.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserLink from 'src/components/user_link/user_link.vue'
import UserPopover from 'src/components/user_popover/user_popover.vue'
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
import {
highlightClass,
highlightStyle,
} from '../../services/user_highlighter/user_highlighter.js'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import Report from '../report/report.vue'
import Status from '../status/status.vue'
import StatusContent from '../status_content/status_content.vue'
import Timeago from '../timeago/timeago.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserCard from '../user_card/user_card.vue'
import UserLink from '../user_link/user_link.vue'
import UserPopover from '../user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -64,14 +61,15 @@ const Notification = {
components: {
StatusContent,
UserAvatar,
UserCard,
Timeago,
Status,
Report,
RichContent,
UserPopover,
UserLink,
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
},
mounted() {
document.addEventListener('selectionchange', this.onContentSelect)

View file

@ -267,7 +267,7 @@
</div>
</div>
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingApproveConfirmDialog"
:title="$t('user_card.approve_confirm_title')"
:confirm-text="$t('user_card.approve_confirm_accept_button')"
@ -276,8 +276,8 @@
@cancelled="hideApproveConfirmDialog"
>
{{ $t('user_card.approve_confirm', { user: user.screen_name_ui }) }}
</confirm-modal>
<confirm-modal
</ConfirmModal>
<ConfirmModal
v-if="showingDenyConfirmDialog"
:title="$t('user_card.deny_confirm_title')"
:confirm-text="$t('user_card.deny_confirm_accept_button')"
@ -286,7 +286,7 @@
@cancelled="hideDenyConfirmDialog"
>
{{ $t('user_card.deny_confirm', { user: user.screen_name_ui }) }}
</confirm-modal>
</ConfirmModal>
</teleport>
</article>
</template>

View file

@ -106,7 +106,7 @@
</template>
<script>
import Popover from '../popover/popover.vue'
import Popover from 'src/components/popover/popover.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'

View file

@ -2,6 +2,8 @@ import { mapState } from 'pinia'
import { computed } from 'vue'
import { mapGetters } from 'vuex'
import ExtraNotifications from 'src/components/extra_notifications/extra_notifications.vue'
import Notification from 'src/components/notification/notification.vue'
import FaviconService from '../../services/favicon_service/favicon_service.js'
import {
ACTIONABLE_NOTIFICATION_TYPES,
@ -11,8 +13,6 @@ import {
unseenNotificationsFromStore,
} from '../../services/notification_utils/notification_utils.js'
import notificationsFetcher from '../../services/notifications_fetcher/notifications_fetcher.service.js'
import ExtraNotifications from '../extra_notifications/extra_notifications.vue'
import Notification from '../notification/notification.vue'
import NotificationFilters from './notification_filters.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
@ -115,6 +115,7 @@ const Notifications = {
return countExtraNotifications(
this.$store,
useMergedConfigStore().mergedConfig,
useAnnouncementsStore().unreadAnnouncementCount,
)
},
unseenCountTitle() {

View file

@ -33,7 +33,7 @@
</template>
<script>
import Checkbox from '../checkbox/checkbox.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
export default {
components: {
Checkbox,

View file

@ -1,5 +1,4 @@
import Checkbox from 'components/checkbox/checkbox.vue'
import RichContent from 'components/rich_content/rich_content.jsx'
import Timeago from 'components/timeago/timeago.vue'
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
@ -12,7 +11,7 @@ export default {
props: ['basePoll', 'emoji'],
components: {
Timeago,
RichContent,
Checkbox,
},
data() {

View file

@ -1,4 +1,4 @@
import Select from '../select/select.vue'
import Select from 'src/components/select/select.vue'
import { useInstanceStore } from 'src/stores/instance.js'

View file

@ -1,24 +1,23 @@
import { debounce, map, reject, uniqBy } from 'lodash'
import { mapActions, mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import { mapGetters } from 'vuex'
import Attachment from 'src/components/attachment/attachment.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import DraftCloser from 'src/components/draft_closer/draft_closer.vue'
import EmojiInput from 'src/components/emoji_input/emoji_input.vue'
import suggestor from 'src/components/emoji_input/suggestor.js'
import Gallery from 'src/components/gallery/gallery.vue'
import MediaUpload from 'src/components/media_upload/media_upload.vue'
import Popover from 'src/components/popover/popover.vue'
import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
import Select from 'src/components/select/select.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import { propsToNative } from '../../services/attributes_helper/attributes_helper.service.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
import statusPoster from '../../services/status_poster/status_poster.service.js'
import Attachment from '../attachment/attachment.vue'
import Checkbox from '../checkbox/checkbox.vue'
import EmojiInput from '../emoji_input/emoji_input.vue'
import suggestor from '../emoji_input/suggestor.js'
import MediaUpload from '../media_upload/media_upload.vue'
import PollForm from '../poll/poll_form.vue'
import QuoteForm from '../quote/quote_form.vue'
import ScopeSelector from '../scope_selector/scope_selector.vue'
import Select from '../select/select.vue'
import StatusContent from '../status_content/status_content.vue'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
@ -141,8 +140,12 @@ const PostStatusForm = {
components: {
MediaUpload,
EmojiInput,
PollForm,
QuoteForm,
PollForm: defineAsyncComponent(
() => import('src/components/poll/poll_form.vue'),
),
QuoteForm: defineAsyncComponent(
() => import('src/components/quote/quote_form.vue'),
),
ScopeSelector,
Checkbox,
Select,

View file

@ -396,7 +396,7 @@
/>
</button>
</div>
<gallery
<Gallery
v-if="newStatus.files && newStatus.files.length > 0"
class="attachments"
:grid="true"

View file

@ -1,7 +1,8 @@
import get from 'lodash/get'
import { get } from 'lodash'
import { defineAsyncComponent } from 'vue'
import Modal from '../modal/modal.vue'
import PostStatusForm from '../post_status_form/post_status_form.vue'
import Modal from 'src/components/modal/modal.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import { usePostStatusStore } from 'src/stores/post_status.js'

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const PublicAndExternalTimeline = {
components: {

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const PublicTimeline = {
components: {

View file

@ -1,6 +1,6 @@
import { mapState } from 'pinia'
import Popover from '../popover/popover.vue'
import Popover from 'src/components/popover/popover.vue'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useLocalConfigStore } from 'src/stores/local_config.js'

View file

@ -6,9 +6,7 @@ import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
library.add(faCircleNotch)
export default {
components: {
Status: defineAsyncComponent(() => import('../status/status.vue')),
},
components: {},
name: 'Quote',
props: {
visible: {

View file

@ -1,6 +1,6 @@
import { debounce } from 'lodash'
import Checkbox from '../checkbox/checkbox.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Quote from './quote.vue'
import { useInstanceStore } from 'src/stores/instance.js'

View file

@ -1,4 +1,4 @@
import Timeline from '../timeline/timeline.vue'
import Timeline from 'src/components/timeline/timeline.vue'
const QuotesTimeline = {
created() {

View file

@ -3,9 +3,9 @@ import { required, requiredIf, sameAs } from '@vuelidate/validators'
import { mapState as mapPiniaState } from 'pinia'
import { mapActions, mapState } from 'vuex'
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
import TermsOfServicePanel from 'src/components/terms_of_service_panel/terms_of_service_panel.vue'
import localeService from '../../services/locale/locale.service.js'
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
import { useInstanceStore } from 'src/stores/instance.js'

View file

@ -1,4 +1,4 @@
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { defineAsyncComponent } from 'vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
@ -11,7 +11,9 @@ export default {
}
},
components: {
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
},
computed: {
label() {

View file

@ -8,7 +8,7 @@
>
{{ label }}
<teleport to="#modal">
<confirm-modal
<ConfirmModal
v-if="showingConfirmRemoveFollower"
:title="$t('user_card.remove_follower_confirm_title')"
:confirm-text="$t('user_card.remove_follower_confirm_accept_button')"
@ -27,7 +27,7 @@
/>
</template>
</i18n-t>
</confirm-modal>
</ConfirmModal>
</teleport>
</button>
</template>

View file

@ -1,7 +1,6 @@
import RichContent from 'src/components/rich_content/rich_content.jsx'
import Select from '../select/select.vue'
import StatusContent from '../status_content/status_content.vue'
import Timeago from '../timeago/timeago.vue'
import Select from 'src/components/select/select.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import Timeago from 'src/components/timeago/timeago.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useReportsStore } from 'src/stores/reports.js'
@ -14,7 +13,6 @@ const Report = {
Select,
StatusContent,
Timeago,
RichContent,
},
computed: {
report() {

View file

@ -33,7 +33,7 @@
</template>
<script>
import Checkbox from '../checkbox/checkbox.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
export default {
components: {
Checkbox,

View file

@ -1,10 +1,8 @@
import { uniqBy } from 'lodash'
import map from 'lodash/map'
import { map, uniqBy } from 'lodash'
import Conversation from 'src/components/conversation/conversation.vue'
import FollowCard from 'src/components/follow_card/follow_card.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import Conversation from '../conversation/conversation.vue'
import FollowCard from '../follow_card/follow_card.vue'
import Status from '../status/status.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch, faSearch } from '@fortawesome/free-solid-svg-icons'
@ -15,7 +13,7 @@ const Search = {
components: {
FollowCard,
Conversation,
Status,
TabSwitcher,
},
props: ['query'],

View file

@ -1,5 +1,5 @@
import Checkbox from '../checkbox/checkbox.vue'
import List from '../list/list.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import List from 'src/components/list/list.vue'
const SelectableList = {
components: {

View file

@ -1,9 +1,9 @@
import Checkbox from 'components/checkbox/checkbox.vue'
import ConfirmModal from 'components/confirm_modal/confirm_modal.vue'
import Popover from 'components/popover/popover.vue'
import Select from 'components/select/select.vue'
import StillImage from 'components/still-image/still-image.vue'
import { assign, clone } from 'lodash'
import { defineAsyncComponent } from 'vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import EmojiEditingPopover from '../helpers/emoji_editing_popover.vue'
@ -33,7 +33,10 @@ const EmojiTab = {
StillImage,
Select,
Popover,
ConfirmModal,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
ModifiedIndicator,
EmojiEditingPopover,
},

View file

@ -149,13 +149,20 @@
</template>
<script>
import ConfirmModal from 'components/confirm_modal/confirm_modal.vue'
import Popover from 'components/popover/popover.vue'
import SelectComponent from 'components/select/select.vue'
import StillImage from 'components/still-image/still-image.vue'
import { defineAsyncComponent } from 'vue'
export default {
components: { Popover, ConfirmModal, StillImage, SelectComponent },
components: {
Popover,
ConfirmModal: defineAsyncComponent(
() => import('src/components/confirm_modal/confirm_modal.vue'),
),
SelectComponent,
},
inject: ['emojiAddr'],
props: {
placement: {

Some files were not shown because too many files have changed in this diff Show more