refactor: dialogs (#1224)

* refactor: dialogs

* fix: storeAvatarImage

* FriendLog.vue

* FriendLog.vue

* FriendLog.vue

* GameLog.vue

* fix: next day button jumping to the wrong date

* sync master

* fix: launchGame

* Notification.vue

* Feed.vue

* Search.vue

* Profile.vue

* PlayerList.vue

* Login.vue

* utils

* update dialog

* del gameLog.pug

* fix

* fix: group role cannot be displayed currently

* fix: "Hide Friends in Same Instance" hides players in unrelated private instances (#1210)

* fix

* fix: "Hide Friends in Same Instance" does not work when "Split Favorite Friends" is enabled

* fix Notification.vue message

* fix: deleteFavoriteNoConfirm

* fix: feed status style

* fix: infinite loading when deleting note

* fix: private players will not be hidden when 'Hide Friends in Same Instance', and 'Hide Friends in Same Instance' will not work when 'Split Favorite Friends'
This commit is contained in:
pa
2025-05-14 19:01:15 +09:00
committed by GitHub
parent 5ca028b30a
commit e792ed481b
130 changed files with 14208 additions and 10462 deletions

View File

@@ -0,0 +1,725 @@
<template>
<div v-if="menuActiveIndex === 'profile'" class="x-container">
<div class="options-container" style="margin-top: 0">
<span class="header">{{ t('view.profile.profile.header') }}</span>
<div class="x-friend-list" style="margin-top: 10px">
<div class="x-friend-item" @click="showUserDialog(API.currentUser.id)">
<div class="avatar">
<img v-lazy="userImage(API.currentUser, true)" />
</div>
<div class="detail">
<span class="name" v-text="API.currentUser.displayName"></span>
<span class="extra" v-text="API.currentUser.username"></span>
</div>
</div>
<div class="x-friend-item" style="cursor: default">
<div class="detail">
<span class="name">{{ t('view.profile.profile.last_activity') }}</span>
<span class="extra">{{ API.currentUser.last_activity | formatDate('long') }}</span>
</div>
</div>
<div class="x-friend-item" style="cursor: default">
<div class="detail">
<span class="name">{{ t('view.profile.profile.two_factor') }}</span>
<span class="extra">{{
API.currentUser.twoFactorAuthEnabled
? t('view.profile.profile.two_factor_enabled')
: t('view.profile.profile.two_factor_disabled')
}}</span>
</div>
</div>
<div class="x-friend-item" @click="getVRChatCredits()">
<div class="detail">
<span class="name">{{ t('view.profile.profile.vrchat_credits') }}</span>
<span class="extra">{{ vrchatCredit ?? t('view.profile.profile.refresh') }}</span>
</div>
</div>
</div>
<div style="margin-top: 10px">
<el-button
size="small"
type="danger"
plain
icon="el-icon-switch-button"
style="margin-left: 0; margin-right: 5px; margin-top: 10px"
@click="logout()"
>{{ t('view.profile.profile.logout') }}</el-button
>
<el-button
size="small"
icon="el-icon-picture-outline"
style="margin-left: 0; margin-right: 5px; margin-top: 10px"
@click="showGalleryDialog()"
>{{ t('view.profile.profile.manage_gallery_icon') }}</el-button
>
<el-button
size="small"
icon="el-icon-chat-dot-round"
style="margin-left: 0; margin-right: 5px; margin-top: 10px"
@click="showDiscordNamesDialog()"
>{{ t('view.profile.profile.discord_names') }}</el-button
>
<el-button
size="small"
icon="el-icon-printer"
style="margin-left: 0; margin-right: 5px; margin-top: 10px"
@click="showExportFriendsListDialog()"
>{{ t('view.profile.profile.export_friend_list') }}</el-button
>
<el-button
size="small"
icon="el-icon-user"
style="margin-left: 0; margin-right: 5px; margin-top: 10px"
@click="showExportAvatarsListDialog()"
>{{ t('view.profile.profile.export_own_avatars') }}</el-button
>
</div>
</div>
<div class="options-container">
<span class="header">{{ t('view.profile.game_info.header') }}</span>
<div class="x-friend-list" style="margin-top: 10px">
<div class="x-friend-item">
<div class="detail" @click="getVisits">
<span class="name">{{ t('view.profile.game_info.online_users') }}</span>
<span v-if="visits" class="extra">{{
t('view.profile.game_info.user_online', { count: visits })
}}</span>
<span v-else class="extra">{{ t('view.profile.game_info.refresh') }}</span>
</div>
</div>
</div>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.vrc_sdk_downloads.header') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="API.getConfig()"></el-button>
</el-tooltip>
</div>
<div class="x-friend-list" style="margin-top: 10px">
<div
v-for="(link, item) in API.cachedConfig.downloadUrls"
:key="item"
class="x-friend-item"
placement="top">
<div class="detail" @click="openExternalLink(link)">
<span class="name" v-text="item"></span>
<span class="extra" v-text="link"></span>
</div>
</div>
</div>
</div>
<div class="options-container">
<span class="header">{{ t('view.profile.direct_access.header') }}</span>
<div style="margin-top: 10px">
<el-button-group>
<el-button size="small" @click="promptUsernameDialog()">{{
t('view.profile.direct_access.username')
}}</el-button>
<el-button size="small" @click="promptUserIdDialog()">{{
t('view.profile.direct_access.user_id')
}}</el-button>
<el-button size="small" @click="promptWorldDialog()">{{
t('view.profile.direct_access.world_instance')
}}</el-button>
<el-button size="small" @click="promptAvatarDialog()">{{
t('view.profile.direct_access.avatar')
}}</el-button>
</el-button-group>
</div>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.invite_messages') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="
inviteMessageTable.visible = true;
refreshInviteMessageTable('message');
"></el-button>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.profile.clear_results_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click="inviteMessageTable.visible = false"></el-button>
</el-tooltip>
</div>
<data-tables v-if="inviteMessageTable.visible" v-bind="inviteMessageTable" style="margin-top: 10px">
<el-table-column
:label="t('table.profile.invite_messages.slot')"
prop="slot"
sortable="custom"
width="70"></el-table-column>
<el-table-column :label="t('table.profile.invite_messages.message')" prop="message"></el-table-column>
<el-table-column
:label="t('table.profile.invite_messages.cool_down')"
prop="updatedAt"
sortable="custom"
width="110"
align="right">
<template #default="scope">
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
</template>
</el-table-column>
<el-table-column :label="t('table.profile.invite_messages.action')" width="60" align="right">
<template #default="scope">
<el-button
type="text"
icon="el-icon-edit"
size="mini"
@click="showEditInviteMessageDialog('message', scope.row)"></el-button>
</template>
</el-table-column>
</data-tables>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.invite_response_messages') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="
inviteResponseMessageTable.visible = true;
refreshInviteMessageTable('response');
"></el-button>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.profile.clear_results_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click="inviteResponseMessageTable.visible = false"></el-button>
</el-tooltip>
</div>
<data-tables
v-if="inviteResponseMessageTable.visible"
v-bind="inviteResponseMessageTable"
style="margin-top: 10px">
<el-table-column
:label="t('table.profile.invite_messages.slot')"
prop="slot"
sortable="custom"
width="70"></el-table-column>
<el-table-column :label="t('table.profile.invite_messages.message')" prop="message"></el-table-column>
<el-table-column
:label="t('table.profile.invite_messages.cool_down')"
prop="updatedAt"
sortable="custom"
width="110"
align="right">
<template #default="scope">
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
</template>
</el-table-column>
<el-table-column :label="t('table.profile.invite_messages.action')" width="60" align="right">
<template #default="scope">
<el-button
type="text"
icon="el-icon-edit"
size="mini"
@click="showEditInviteMessageDialog('response', scope.row)"></el-button>
</template>
</el-table-column>
</data-tables>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.invite_request_messages') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="
inviteRequestMessageTable.visible = true;
refreshInviteMessageTable('request');
"></el-button>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.profile.clear_results_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click="inviteRequestMessageTable.visible = false"></el-button>
</el-tooltip>
</div>
<data-tables
v-if="inviteRequestMessageTable.visible"
v-bind="inviteRequestMessageTable"
style="margin-top: 10px">
<el-table-column
:label="t('table.profile.invite_messages.slot')"
prop="slot"
sortable="custom"
width="70"></el-table-column>
<el-table-column :label="t('table.profile.invite_messages.message')" prop="message"></el-table-column>
<el-table-column
:label="t('table.profile.invite_messages.cool_down')"
prop="updatedAt"
sortable="custom"
width="110"
align="right">
<template #default="scope">
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
</template>
</el-table-column>
<el-table-column :label="t('table.profile.invite_messages.action')" width="60" align="right">
<template #default="scope">
<el-button
type="text"
icon="el-icon-edit"
size="mini"
@click="showEditInviteMessageDialog('request', scope.row)"></el-button>
</template>
</el-table-column>
</data-tables>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.invite_request_response_messages') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="
inviteRequestResponseMessageTable.visible = true;
refreshInviteMessageTable('requestResponse');
"></el-button>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.profile.clear_results_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click="inviteRequestResponseMessageTable.visible = false"></el-button>
</el-tooltip>
</div>
<data-tables
v-if="inviteRequestResponseMessageTable.visible"
v-bind="inviteRequestResponseMessageTable"
style="margin-top: 10px">
<el-table-column
:label="t('table.profile.invite_messages.slot')"
prop="slot"
sortable="custom"
width="70"></el-table-column>
<el-table-column :label="t('table.profile.invite_messages.message')" prop="message"></el-table-column>
<el-table-column
:label="t('table.profile.invite_messages.cool_down')"
prop="updatedAt"
sortable="custom"
width="110"
align="right">
<template #default="scope">
<countdown-timer :datetime="scope.row.updatedAt" :hours="1"></countdown-timer>
</template>
</el-table-column>
<el-table-column :label="t('table.profile.invite_messages.action')" width="60" align="right">
<template #default="scope">
<el-button
type="text"
icon="el-icon-edit"
size="mini"
@click="showEditInviteMessageDialog('requestResponse', scope.row)"></el-button>
</template>
</el-table-column>
</data-tables>
</div>
<div class="options-container">
<span class="header">{{ t('view.profile.past_display_names') }}</span>
<data-tables v-bind="pastDisplayNameTable" style="margin-top: 10px">
<el-table-column
:label="t('table.profile.previous_display_name.date')"
prop="updated_at"
sortable="custom">
<template #default="scope">
<span>{{ scope.row.updated_at | formatDate('long') }}</span>
</template>
</el-table-column>
<el-table-column
:label="t('table.profile.previous_display_name.name')"
prop="displayName"></el-table-column>
</data-tables>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.config_json') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="refreshConfigTreeData()"></el-button>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.profile.clear_results_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click="configTreeData = []"></el-button>
</el-tooltip>
</div>
<el-tree v-if="configTreeData.length > 0" :data="configTreeData" style="margin-top: 10px; font-size: 12px">
<template #default="scope">
<span>
<span style="font-weight: bold; margin-right: 5px" v-text="scope.data.key"></span>
<span v-if="!scope.data.children" v-text="scope.data.value"></span>
</span>
</template>
</el-tree>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.current_user_json') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="refreshCurrentUserTreeData()"></el-button>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.profile.clear_results_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click="currentUserTreeData = []"></el-button>
</el-tooltip>
</div>
<el-tree
v-if="currentUserTreeData.length > 0"
:data="currentUserTreeData"
style="margin-top: 10px; font-size: 12px">
<template #default="scope">
<span>
<span style="font-weight: bold; margin-right: 5px" v-text="scope.data.key"></span>
<span v-if="!scope.data.children" v-text="scope.data.value"></span>
</span>
</template>
</el-tree>
</div>
<div class="options-container">
<div class="header-bar">
<span class="header">{{ t('view.profile.feedback') }}</span>
<el-tooltip placement="top" :content="t('view.profile.refresh_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-refresh"
circle
style="margin-left: 5px"
@click="getCurrentUserFeedback()"></el-button>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.profile.clear_results_tooltip')" :disabled="hideTooltips">
<el-button
type="default"
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click="currentUserFeedbackData = []"></el-button>
</el-tooltip>
</div>
<el-tree
v-if="currentUserFeedbackData.length > 0"
:data="currentUserFeedbackData"
style="margin-top: 10px; font-size: 12px">
<template #default="scope">
<span>
<span style="font-weight: bold; margin-right: 5px" v-text="scope.data.key"></span>
<span v-if="!scope.data.children" v-text="scope.data.value"></span>
</span>
</template>
</el-tree>
</div>
<DiscordNamesDialog :discord-names-dialog-visible.sync="discordNamesDialogVisible" :friends="friends" />
<ExportFriendsListDialog
:is-export-friends-list-dialog-visible.sync="isExportFriendsListDialogVisible"
:friends="friends" />
<ExportAvatarsListDialog :is-export-avatars-list-dialog-visible.sync="isExportAvatarsListDialogVisible" />
</div>
</template>
<script>
export default {
name: 'ProfileTab'
};
</script>
<script setup>
import { inject, ref, getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { inviteMessagesRequest, miscRequest, userRequest } from '../../api';
import utils from '../../classes/utils';
import { parseAvatarUrl } from '../../composables/avatar/utils';
import DiscordNamesDialog from './dialogs/DiscordNamesDialog.vue';
import ExportFriendsListDialog from './dialogs/ExportFriendsListDialog.vue';
import ExportAvatarsListDialog from './dialogs/ExportAvatarsListDialog.vue';
const { t } = useI18n();
const { $prompt, $message } = getCurrentInstance().proxy;
const API = inject('API');
const userImage = inject('userImage');
const showUserDialog = inject('showUserDialog');
const showAvatarDialog = inject('showAvatarDialog');
const showGalleryDialog = inject('showGalleryDialog');
const openExternalLink = inject('openExternalLink');
const props = defineProps({
menuActiveIndex: {
type: String,
default: 'profile'
},
hideTooltips: {
type: Boolean,
default: false
},
inviteMessageTable: {
type: Object,
default: () => ({
visible: false,
data: []
})
},
inviteResponseMessageTable: {
type: Object,
default: () => ({
visible: false,
data: []
})
},
inviteRequestMessageTable: {
type: Object,
default: () => ({
visible: false,
data: []
})
},
inviteRequestResponseMessageTable: {
type: Object,
default: () => ({
visible: false,
data: []
})
},
pastDisplayNameTable: {
type: Object,
default: () => ({
visible: false,
data: []
})
},
friends: {
type: Map,
default: () => new Map()
},
directAccessWorld: {
type: Function,
default: () => {}
}
});
const emit = defineEmits(['logout', 'lookupUser', 'showEditInviteMessageDialog']);
const vrchatCredit = ref(null);
const configTreeData = ref([]);
const currentUserTreeData = ref([]);
const currentUserFeedbackData = ref([]);
const discordNamesDialogVisible = ref(false);
const isExportFriendsListDialogVisible = ref(false);
const isExportAvatarsListDialogVisible = ref(false);
const visits = ref(0);
function getVisits() {
miscRequest.getVisits().then((args) => {
// API.$on('VISITS')
visits.value = args.json;
});
}
function getVRChatCredits() {
// API.$on('VRCCREDITS')
miscRequest.getVRChatCredits().then((args) => (vrchatCredit.value = args.json?.balance));
}
function logout() {
emit('logout');
}
function showDiscordNamesDialog() {
discordNamesDialogVisible.value = true;
}
function showExportFriendsListDialog() {
isExportFriendsListDialogVisible.value = true;
}
function showExportAvatarsListDialog() {
isExportAvatarsListDialogVisible.value = true;
}
function promptUsernameDialog() {
$prompt(t('prompt.direct_access_username.description'), t('prompt.direct_access_username.header'), {
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.direct_access_username.ok'),
cancelButtonText: t('prompt.direct_access_username.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.direct_access_username.input_error'),
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
emit('lookupUser', {
displayName: instance.inputValue
});
}
}
});
}
function promptUserIdDialog() {
$prompt(t('prompt.direct_access_user_id.description'), t('prompt.direct_access_user_id.header'), {
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.direct_access_user_id.ok'),
cancelButtonText: t('prompt.direct_access_user_id.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.direct_access_user_id.input_error'),
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
const testUrl = instance.inputValue.substring(0, 15);
if (testUrl === 'https://vrchat.') {
const userId = this.parseUserUrl(instance.inputValue);
if (userId) {
showUserDialog(userId);
} else {
$message({
message: t('prompt.direct_access_user_id.message.error'),
type: 'error'
});
}
} else {
showUserDialog(instance.inputValue);
}
}
}
});
}
function promptWorldDialog() {
$prompt(t('prompt.direct_access_world_id.description'), t('prompt.direct_access_world_id.header'), {
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.direct_access_world_id.ok'),
cancelButtonText: t('prompt.direct_access_world_id.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.direct_access_world_id.input_error'),
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
if (!props.directAccessWorld(instance.inputValue)) {
$message({
message: t('prompt.direct_access_world_id.message.error'),
type: 'error'
});
}
}
}
});
}
function promptAvatarDialog() {
$prompt(t('prompt.direct_access_avatar_id.description'), t('prompt.direct_access_avatar_id.header'), {
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.direct_access_avatar_id.ok'),
cancelButtonText: t('prompt.direct_access_avatar_id.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.direct_access_avatar_id.input_error'),
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
const testUrl = instance.inputValue.substring(0, 15);
if (testUrl === 'https://vrchat.') {
const avatarId = parseAvatarUrl(instance.inputValue);
if (avatarId) {
showAvatarDialog(avatarId);
} else {
$message({
message: t('prompt.direct_access_avatar_id.message.error'),
type: 'error'
});
}
} else {
showAvatarDialog(instance.inputValue);
}
}
}
});
}
function showEditInviteMessageDialog(messageType, inviteMessage) {
emit('showEditInviteMessageDialog', {
messageType,
inviteMessage
});
}
function refreshInviteMessageTable(messageType) {
inviteMessagesRequest.refreshInviteMessageTableData(messageType);
}
async function refreshConfigTreeData() {
await API.getConfig();
configTreeData.value = utils.buildTreeData(API.cachedConfig);
}
async function refreshCurrentUserTreeData() {
await API.getCurrentUser();
currentUserTreeData.value = utils.buildTreeData(API.currentUser);
}
function getCurrentUserFeedback() {
userRequest.getUserFeedback({ userId: API.currentUser.id }).then((args) => {
// API.$on('USER:FEEDBACK')
if (args.params.userId === API.currentUser.id) {
currentUserFeedbackData.value = utils.buildTreeData(args.json);
}
});
}
</script>

View File

@@ -1,13 +1,10 @@
<template>
<el-dialog
<safe-dialog
class="x-dialog"
:before-close="beforeDialogClose"
:visible="discordNamesDialogVisible"
:title="t('dialog.discord_names.header')"
width="650px"
@close="closeDialog"
@mousedown.native="dialogMouseDown"
@mouseup.native="dialogMouseUp">
@close="closeDialog">
<div style="font-size: 12px">
{{ t('dialog.discord_names.description') }}
</div>
@@ -19,7 +16,7 @@
resize="none"
readonly
style="margin-top: 15px" />
</el-dialog>
</safe-dialog>
</template>
<script setup>
@@ -27,9 +24,6 @@
import { useI18n } from 'vue-i18n-bridge';
const API = inject('API');
const beforeDialogClose = inject('beforeDialogClose');
const dialogMouseDown = inject('dialogMouseDown');
const dialogMouseUp = inject('dialogMouseUp');
const { t } = useI18n();

View File

@@ -1,13 +1,10 @@
<template>
<el-dialog
<safe-dialog
class="x-dialog"
:before-close="beforeDialogClose"
:visible="editInviteMessageDialog.visible"
:title="t('dialog.edit_invite_message.header')"
width="400px"
@close="closeDialog"
@mousedown.native="dialogMouseDown"
@mouseup.native="dialogMouseUp">
@close="closeDialog">
<div style="font-size: 12px">
<span>{{ t('dialog.edit_invite_message.description') }}</span>
<el-input
@@ -23,10 +20,10 @@
<template #footer>
<el-button type="small" @click="closeDialog">{{ $t('dialog.edit_invite_message.cancel') }}</el-button>
<el-button type="primary" size="small" @click="saveEditInviteMessage">{{
$t('dialog.edit_invite_message.save')
t('dialog.edit_invite_message.save')
}}</el-button>
</template>
</el-dialog>
</safe-dialog>
</template>
<script setup>
@@ -38,9 +35,6 @@
const instance = getCurrentInstance();
const $message = instance.proxy.$message;
const API = inject('API');
const beforeDialogClose = inject('beforeDialogClose');
const dialogMouseDown = inject('dialogMouseDown');
const dialogMouseUp = inject('dialogMouseUp');
const props = defineProps({
editInviteMessageDialog: {

View File

@@ -1,11 +1,5 @@
<template>
<el-dialog
:before-close="beforeDialogClose"
:visible.sync="isVisible"
:title="$t('dialog.export_own_avatars.header')"
width="650px"
@mousedown.native="dialogMouseDown"
@mouseup.native="dialogMouseUp">
<safe-dialog :visible.sync="isVisible" :title="$t('dialog.export_own_avatars.header')" width="650px">
<el-input
v-model="exportAvatarsListCsv"
v-loading="loading"
@@ -16,7 +10,7 @@
readonly
style="margin-top: 15px"
@click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()" />
</el-dialog>
</safe-dialog>
</template>
<script>
@@ -24,7 +18,7 @@
export default {
name: 'ExportAvatarsListDialog',
inject: ['API', 'beforeDialogClose', 'dialogMouseDown', 'dialogMouseUp'],
inject: ['API'],
props: {
isExportAvatarsListDialogVisible: Boolean
},

View File

@@ -1,11 +1,5 @@
<template>
<el-dialog
:before-close="beforeDialogClose"
:title="$t('dialog.export_friends_list.header')"
:visible.sync="isVisible"
width="650px"
@mousedown.native="dialogMouseDown"
@mouseup.native="dialogMouseUp">
<safe-dialog :title="$t('dialog.export_friends_list.header')" :visible.sync="isVisible" width="650px">
<el-tabs type="card">
<el-tab-pane :label="$t('dialog.export_friends_list.csv')">
<el-input
@@ -30,13 +24,13 @@
@click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()" />
</el-tab-pane>
</el-tabs>
</el-dialog>
</safe-dialog>
</template>
<script>
export default {
name: 'ExportFriendsListDialog',
inject: ['API', 'beforeDialogClose', 'dialogMouseDown', 'dialogMouseUp'],
inject: ['API'],
props: {
friends: Map,
isExportFriendsListDialogVisible: Boolean