mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-24 01:03:50 +02:00
refactor: resolve lag issues when opening the world dialog in the favorites worlds tab (#1156) (#1168)
* refactor: resolve lag issues when opening the world dialog in the favorite world tab (#1156) * fix
This commit is contained in:
@@ -17,8 +17,7 @@
|
||||
<i
|
||||
slot="reference"
|
||||
class="el-icon-info"
|
||||
style="margin-left: 5px; font-size: 12px; opacity: 0.7"
|
||||
></i>
|
||||
style="margin-left: 5px; font-size: 12px; opacity: 0.7"></i>
|
||||
</el-popover>
|
||||
</div>
|
||||
|
||||
@@ -36,8 +35,7 @@
|
||||
v-model.lazy="barWidth"
|
||||
:max="50"
|
||||
:min="1"
|
||||
@change="changeBarWidth"
|
||||
></el-slider>
|
||||
@change="changeBarWidth"></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
@@ -54,8 +52,7 @@
|
||||
<span>{{ $t('view.charts.instance_activity.settings.show_no_friend_instance') }}</span>
|
||||
<el-switch
|
||||
v-model="isNoFriendInstanceVisible"
|
||||
@change="changeIsNoFriendInstanceVisible"
|
||||
>
|
||||
@change="changeIsNoFriendInstanceVisible">
|
||||
</el-switch>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,8 +65,7 @@
|
||||
<el-button
|
||||
icon="el-icon-arrow-left"
|
||||
:disabled="isPrevDayBtnDisabled"
|
||||
@click="changeSelectedDateFromBtn(false)"
|
||||
></el-button>
|
||||
@click="changeSelectedDateFromBtn(false)"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('view.charts.instance_activity.next_day')" placement="top">
|
||||
<el-button :disabled="isNextDayBtnDisabled" @click="changeSelectedDateFromBtn(true)"
|
||||
@@ -85,8 +81,7 @@
|
||||
:picker-options="{
|
||||
disabledDate: (time) => getDatePickerDisabledDate(time)
|
||||
}"
|
||||
@change="reloadData"
|
||||
></el-date-picker>
|
||||
@change="reloadData"></el-date-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div style="position: relative">
|
||||
@@ -115,8 +110,7 @@
|
||||
:is-dark-mode="isDarkMode"
|
||||
:dt-hour12="dtHour12"
|
||||
:bar-width="barWidth"
|
||||
@open-previous-instance-info-dialog="$emit('open-previous-instance-info-dialog', $event)"
|
||||
/>
|
||||
@open-previous-instance-info-dialog="$emit('open-previous-instance-info-dialog', $event)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -292,46 +286,79 @@
|
||||
initEcharts() {
|
||||
const chartsHeight = this.activityData.length * (this.barWidth + 10) + 200;
|
||||
const chartDom = this.$refs.activityChartRef;
|
||||
if (!this.echartsInstance) {
|
||||
|
||||
const afterInit = () => {
|
||||
this.echartsInstance.resize({
|
||||
height: chartsHeight,
|
||||
animation: {
|
||||
duration: 300
|
||||
}
|
||||
});
|
||||
|
||||
const handleClickYAxisLabel = (params) => {
|
||||
const detailDataIdx = this.filteredActivityDetailData.findIndex((arr) => {
|
||||
const sameLocation = arr[0]?.location === this.activityData[params?.dataIndex]?.location;
|
||||
const sameJoinTime = arr
|
||||
.find((item) => item.user_id === this.API.currentUser.id)
|
||||
?.joinTime.isSame(this.activityData[params?.dataIndex].joinTime);
|
||||
return sameLocation && sameJoinTime;
|
||||
});
|
||||
if (detailDataIdx === -1) {
|
||||
// no detail chart down below, it's hidden, so can't find instance data index
|
||||
console.error(
|
||||
"handleClickYAxisLabel failed, likely current user wasn't in this instance.",
|
||||
params
|
||||
);
|
||||
} else {
|
||||
this.$refs.activityDetailChartRef[detailDataIdx].$el.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const options = this.activityData.length ? this.getNewOption() : {};
|
||||
|
||||
this.echartsInstance.setOption(options, { lazyUpdate: true });
|
||||
this.echartsInstance.on('click', 'yAxis', handleClickYAxisLabel);
|
||||
this.isLoading = false;
|
||||
};
|
||||
|
||||
const initEchartsInstance = () => {
|
||||
this.echartsInstance = this.echarts.init(chartDom, `${this.isDarkMode ? 'dark' : null}`, {
|
||||
height: chartsHeight
|
||||
});
|
||||
this.resizeObserver.observe(chartDom);
|
||||
}
|
||||
|
||||
this.echartsInstance.resize({
|
||||
height: chartsHeight,
|
||||
animation: {
|
||||
duration: 300
|
||||
}
|
||||
});
|
||||
|
||||
const handleClickYAxisLabel = (params) => {
|
||||
const detailDataIdx = this.filteredActivityDetailData.findIndex((arr) => {
|
||||
const sameLocation = arr[0]?.location === this.activityData[params?.dataIndex]?.location;
|
||||
const sameJoinTime = arr
|
||||
.find((item) => item.user_id === this.API.currentUser.id)
|
||||
?.joinTime.isSame(this.activityData[params?.dataIndex].joinTime);
|
||||
return sameLocation && sameJoinTime;
|
||||
});
|
||||
if (detailDataIdx === -1) {
|
||||
console.error(
|
||||
"handleClickYAxisLabel failed, likely current user wasn't in this instance",
|
||||
params
|
||||
);
|
||||
} else {
|
||||
this.$refs.activityDetailChartRef[detailDataIdx].$el.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const options = this.activityData.length ? this.getNewOption() : {};
|
||||
const loadEchartsWithTimeout = () => {
|
||||
const timeout = 5000;
|
||||
let time = 0;
|
||||
const timer = setInterval(() => {
|
||||
if (this.echarts) {
|
||||
initEchartsInstance();
|
||||
afterInit();
|
||||
clearInterval(timer);
|
||||
return;
|
||||
}
|
||||
time += 100;
|
||||
if (time >= timeout) {
|
||||
clearInterval(timer);
|
||||
console.error('echarts init timeout');
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
this.echartsInstance.setOption(options, { lazyUpdate: true });
|
||||
this.echartsInstance.on('click', 'yAxis', handleClickYAxisLabel);
|
||||
this.isLoading = false;
|
||||
if (!this.echartsInstance) {
|
||||
if (!this.echarts) {
|
||||
loadEchartsWithTimeout();
|
||||
} else {
|
||||
initEchartsInstance();
|
||||
afterInit();
|
||||
}
|
||||
} else {
|
||||
afterInit();
|
||||
}
|
||||
},
|
||||
getNewOption() {
|
||||
const getTooltip = (params) => {
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
export default {
|
||||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
name: 'Location',
|
||||
inject: ['API'],
|
||||
inject: {
|
||||
// prevent randomly error
|
||||
// not good idea, it's temporary
|
||||
API: { default: window.API },
|
||||
getWorldName: { default: window.$app?.getWorldName },
|
||||
getGroupName: { default: window.$app?.getGroupName }
|
||||
},
|
||||
props: {
|
||||
location: String,
|
||||
traveling: String,
|
||||
@@ -82,8 +88,7 @@
|
||||
} else if (L.worldId) {
|
||||
var ref = this.API.cachedWorlds.get(L.worldId);
|
||||
if (typeof ref === 'undefined') {
|
||||
// TODO: USE props
|
||||
$app.getWorldName(L.worldId).then((worldName) => {
|
||||
this.getWorldName(L.worldId).then((worldName) => {
|
||||
if (L.tag === instanceId) {
|
||||
if (L.instanceId) {
|
||||
this.text = `${worldName} #${L.instanceName} ${L.accessTypeName}`;
|
||||
@@ -102,8 +107,7 @@
|
||||
this.groupName = this.grouphint;
|
||||
} else if (L.groupId) {
|
||||
this.groupName = L.groupId;
|
||||
// TODO: USE props
|
||||
$app.getGroupName(instanceId).then((groupName) => {
|
||||
this.getGroupName(instanceId).then((groupName) => {
|
||||
if (L.tag === instanceId) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
@@ -153,5 +157,3 @@
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
222
src/components/favorites/FavoritesWorldItem.vue
Normal file
222
src/components/favorites/FavoritesWorldItem.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<div @click="$emit('click')" :style="{ display: 'inline-block', width: '300px', marginRight: '15px' }">
|
||||
<div class="x-friend-item">
|
||||
<template v-if="isLocalFavorite ? favorite.name : favorite.ref">
|
||||
<div class="avatar">
|
||||
<img v-lazy="localFavFakeRef.thumbnailImageUrl" />
|
||||
</div>
|
||||
<div class="detail">
|
||||
<span class="name">{{ localFavFakeRef.name }}</span>
|
||||
<span v-if="localFavFakeRef.occupants" class="extra"
|
||||
>{{ localFavFakeRef.authorName }} ({{ localFavFakeRef.occupants }})</span
|
||||
>
|
||||
<span v-else class="extra">{{ localFavFakeRef.authorName }}</span>
|
||||
</div>
|
||||
<template v-if="editFavoritesMode">
|
||||
<el-dropdown trigger="click" size="mini" style="margin-left: 5px" @click.native.stop>
|
||||
<el-tooltip
|
||||
placement="left"
|
||||
:content="$t(localFavFakeRef ? 'view.favorite.copy_tooltip' : 'view.favorite.move_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button type="default" icon="el-icon-back" size="mini" circle></el-button>
|
||||
</el-tooltip>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<template v-for="groupAPI in API.favoriteWorldGroups">
|
||||
<el-dropdown-item
|
||||
v-if="isLocalFavorite || groupAPI.name !== group.name"
|
||||
:key="groupAPI.name"
|
||||
style="display: block; margin: 10px 0"
|
||||
:disabled="groupAPI.count >= groupAPI.capacity"
|
||||
@click.native="handleDropdownItemClick(groupAPI)">
|
||||
{{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
</el-dropdown-menu>
|
||||
|
||||
<el-button v-if="!isLocalFavorite" type="text" size="mini" @click.stop style="margin-left: 5px">
|
||||
<el-checkbox v-model="isSelected"></el-checkbox>
|
||||
</el-button>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-tooltip
|
||||
v-if="!isLocalFavorite && favorite.deleted"
|
||||
placement="left"
|
||||
:content="$t('view.favorite.unavailable_tooltip')">
|
||||
<i class="el-icon-warning" style="color: #f56c6c; margin-left: 5px"></i>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="!isLocalFavorite && favorite.ref.releaseStatus === 'private'"
|
||||
placement="left"
|
||||
:content="$t('view.favorite.private')">
|
||||
<i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
placement="left"
|
||||
:content="$t('view.favorite.self_invite_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-message"
|
||||
style="margin-left: 5px"
|
||||
@click.stop="$emit('new-instance-self-invite', favorite.id)"
|
||||
circle></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="!isLocalFavorite"
|
||||
placement="right"
|
||||
:content="$t('view.favorite.unfavorite_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
v-if="shiftHeld"
|
||||
size="mini"
|
||||
icon="el-icon-close"
|
||||
circle
|
||||
style="color: #f56c6c; margin-left: 5px"
|
||||
@click.stop="deleteFavorite(favorite.id)"></el-button>
|
||||
<el-button
|
||||
v-else
|
||||
icon="el-icon-star-on"
|
||||
size="mini"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
type="default"
|
||||
@click.stop="showFavoriteDialog(favorite.id)"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<el-tooltip
|
||||
v-if="isLocalFavorite"
|
||||
placement="right"
|
||||
:content="$t('view.favorite.unfavorite_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
v-if="shiftHeld"
|
||||
size="mini"
|
||||
icon="el-icon-close"
|
||||
circle
|
||||
style="color: #f56c6c; margin-left: 5px"
|
||||
@click.stop="$emit('remove-local-world-favorite', favorite.id, group)"></el-button>
|
||||
<el-button
|
||||
v-else
|
||||
icon="el-icon-star-on"
|
||||
size="mini"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
type="default"
|
||||
@click.stop="showFavoriteDialog(favorite.id)"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="avatar"></div>
|
||||
<div class="detail">
|
||||
<span>{{ favorite.name || favorite.id }}</span>
|
||||
<el-tooltip
|
||||
v-if="!isLocalFavorite && favorite.deleted"
|
||||
placement="left"
|
||||
:content="$t('view.favorite.unavailable_tooltip')">
|
||||
<i class="el-icon-warning" style="color: #f56c6c; margin-left: 5px"></i>
|
||||
</el-tooltip>
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-close"
|
||||
size="mini"
|
||||
style="margin-left: 5px"
|
||||
@click.stop="handleDeleteFavorite"></el-button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FavoritesWorldItem',
|
||||
inject: ['API'],
|
||||
props: {
|
||||
group: [Object, String],
|
||||
favorite: Object,
|
||||
editFavoritesMode: Boolean,
|
||||
hideTooltips: Boolean,
|
||||
shiftHeld: Boolean,
|
||||
isLocalFavorite: { type: Boolean, required: false }
|
||||
},
|
||||
computed: {
|
||||
isSelected: {
|
||||
get() {
|
||||
return this.favorite.$selected;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('handle-select', value);
|
||||
}
|
||||
},
|
||||
localFavFakeRef() {
|
||||
// local favorite no "ref" property
|
||||
return this.isLocalFavorite ? this.favorite : this.favorite.ref;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleDropdownItemClick(groupAPI) {
|
||||
if (this.isLocalFavorite) {
|
||||
this.addFavoriteWorld(this.localFavFakeRef, groupAPI, true);
|
||||
} else {
|
||||
this.moveFavorite(this.localFavFakeRef, groupAPI, 'world');
|
||||
}
|
||||
},
|
||||
handleDeleteFavorite() {
|
||||
if (this.isLocalFavorite) {
|
||||
this.$emit('remove-local-world-favorite', this.favorite.id, this.group);
|
||||
} else {
|
||||
this.deleteFavorite(this.favorite.id);
|
||||
}
|
||||
},
|
||||
moveFavorite(ref, group, type) {
|
||||
this.API.deleteFavorite({
|
||||
objectId: ref.id
|
||||
}).then(() => {
|
||||
this.API.addFavorite({
|
||||
type,
|
||||
favoriteId: ref.id,
|
||||
tags: group.name
|
||||
});
|
||||
});
|
||||
},
|
||||
deleteFavorite(objectId) {
|
||||
this.API.deleteFavorite({
|
||||
objectId
|
||||
});
|
||||
// FIXME: 메시지 수정
|
||||
// this.$confirm('Continue? Delete Favorite', 'Confirm', {
|
||||
// confirmButtonText: 'Confirm',
|
||||
// cancelButtonText: 'Cancel',
|
||||
// type: 'info',
|
||||
// callback: (action) => {
|
||||
// if (action === 'confirm') {
|
||||
// API.deleteFavorite({
|
||||
// objectId
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
},
|
||||
addFavoriteWorld(ref, group, message) {
|
||||
// wait API splitting PR Merged
|
||||
return this.API.addFavorite({
|
||||
type: 'world',
|
||||
favoriteId: ref.id,
|
||||
tags: group.name
|
||||
}).then((args) => {
|
||||
if (message) {
|
||||
this.$message({
|
||||
message: 'World added to favorites',
|
||||
type: 'success'
|
||||
});
|
||||
}
|
||||
return args;
|
||||
});
|
||||
},
|
||||
showFavoriteDialog(favoriteId) {
|
||||
this.$emit('show-favorite-dialog', 'world', favoriteId);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
382
src/components/favorites/FavoritesWorldTab.vue
Normal file
382
src/components/favorites/FavoritesWorldTab.vue
Normal file
@@ -0,0 +1,382 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between">
|
||||
<div>
|
||||
<el-button size="small" @click="$emit('show-world-export-dialog')">{{
|
||||
$t('view.favorite.export')
|
||||
}}</el-button>
|
||||
<el-button size="small" style="margin-left: 5px" @click="$emit('show-world-import-dialog')">{{
|
||||
$t('view.favorite.import')
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; font-size: 13px; margin-right: 10px">
|
||||
<span class="name" style="margin-right: 5px; line-height: 10px">{{ $t('view.favorite.sort_by') }}</span>
|
||||
<el-radio-group
|
||||
v-model="sortFav"
|
||||
style="margin-right: 12px"
|
||||
@change="$emit('save-sort-favorites-option')">
|
||||
<el-radio :label="false">{{
|
||||
$t('view.settings.appearance.appearance.sort_favorite_by_name')
|
||||
}}</el-radio>
|
||||
<el-radio :label="true">{{
|
||||
$t('view.settings.appearance.appearance.sort_favorite_by_date')
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-input
|
||||
v-model="worldFavoriteSearch"
|
||||
clearable
|
||||
size="mini"
|
||||
:placeholder="$t('view.favorite.worlds.search')"
|
||||
style="width: 200px"
|
||||
@input="searchWorldFavorites" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-list" style="margin-top: 10px">
|
||||
<div
|
||||
v-for="favorite in worldFavoriteSearchResults"
|
||||
:key="favorite.id"
|
||||
style="display: inline-block; width: 300px; margin-right: 15px"
|
||||
@click="showWorldDialog(favorite.id)">
|
||||
<div class="x-friend-item">
|
||||
<template v-if="favorite.name">
|
||||
<div class="avatar">
|
||||
<img v-lazy="favorite.thumbnailImageUrl" />
|
||||
</div>
|
||||
<div class="detail">
|
||||
<span class="name" v-text="favorite.name"></span>
|
||||
<span v-if="favorite.occupants" class="extra"
|
||||
>{{ favorite.authorName }} ({{ favorite.occupants }})</span
|
||||
>
|
||||
<span v-else class="extra" v-text="favorite.authorName"></span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="avatar"></div>
|
||||
<div class="detail">
|
||||
<span v-text="favorite.id"></span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span style="display: block; margin-top: 20px">{{ $t('view.favorite.worlds.vrchat_favorites') }}</span>
|
||||
<el-collapse style="border: 0">
|
||||
<el-collapse-item v-for="group in API.favoriteWorldGroups" :key="group.name">
|
||||
<template slot="title">
|
||||
<div style="display: flex; align-items: center">
|
||||
<span
|
||||
style="font-weight: bold; font-size: 14px; margin-left: 10px"
|
||||
v-text="group.displayName" />
|
||||
<el-tag
|
||||
style="margin: 1px 0 0 5px"
|
||||
size="mini"
|
||||
:type="userFavoriteWorldsStatusForFavTab(group.visibility)"
|
||||
effect="plain"
|
||||
>{{ group.visibility.charAt(0).toUpperCase() + group.visibility.slice(1) }}</el-tag
|
||||
>
|
||||
<span style="color: #909399; font-size: 12px; margin-left: 10px"
|
||||
>{{ group.count }}/{{ group.capacity }}</span
|
||||
>
|
||||
<el-dropdown trigger="click" size="mini" style="margin-left: 10px" @click.native.stop>
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('view.favorite.visibility_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button type="default" icon="el-icon-view" size="mini" circle />
|
||||
</el-tooltip>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item
|
||||
v-for="visibility in worldGroupVisibilityOptions"
|
||||
v-if="group.visibility !== visibility"
|
||||
:key="visibility"
|
||||
style="display: block; margin: 10px 0"
|
||||
@click.native="changeWorldGroupVisibility(group.name, visibility)"
|
||||
>{{ visibility.charAt(0).toUpperCase() + visibility.slice(1) }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('view.favorite.rename_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-edit"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
@click.stop="$emit('change-favorite-group-name', group)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
placement="right"
|
||||
:content="$t('view.favorite.clear_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-delete"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
@click.stop="$emit('clear-favorite-group', group)" />
|
||||
</el-tooltip>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="group.count" class="x-friend-list" style="margin-top: 10px">
|
||||
<favorites-world-item
|
||||
v-for="favorite in groupedByGroupKeyFavoriteWorlds[group.key]"
|
||||
:key="favorite.id"
|
||||
:group="group"
|
||||
:favorite="favorite"
|
||||
:edit-favorites-mode="editFavoritesMode"
|
||||
:hide-tooltips="hideTooltips"
|
||||
:shift-held="shiftHeld"
|
||||
@click="showWorldDialog(favorite.id)"
|
||||
@handle-select="favorite.$selected = $event"
|
||||
@new-instance-self-invite="newInstanceSelfInvite"
|
||||
@show-favorite-dialog="showFavoriteDialog" />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
style="
|
||||
padding-top: 25px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: rgb(144, 147, 153);
|
||||
">
|
||||
<span>No Data</span>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<span style="display: block; margin-top: 20px">{{ $t('view.favorite.worlds.local_favorites') }}</span>
|
||||
<br />
|
||||
<el-button size="small" @click="promptNewLocalWorldFavoriteGroup">{{
|
||||
$t('view.favorite.worlds.new_group')
|
||||
}}</el-button>
|
||||
<el-button
|
||||
v-if="!refreshingLocalFavorites"
|
||||
size="small"
|
||||
style="margin-left: 5px"
|
||||
@click="$emit('refresh-local-world-favorite')"
|
||||
>{{ $t('view.favorite.worlds.refresh') }}</el-button
|
||||
>
|
||||
<el-button v-else size="small" style="margin-left: 5px" @click="refreshingLocalFavorites = false">
|
||||
<i class="el-icon-loading" style="margin-right: 5px" />
|
||||
<span>{{ $t('view.favorite.worlds.cancel_refresh') }}</span>
|
||||
</el-button>
|
||||
<el-collapse style="border: 0">
|
||||
<el-collapse-item v-for="group in localWorldFavoriteGroups" v-if="localWorldFavorites[group]" :key="group">
|
||||
<template slot="title">
|
||||
<span style="font-weight: bold; font-size: 14px; margin-left: 10px" v-text="group" />
|
||||
<span style="color: #909399; font-size: 12px; margin-left: 10px">{{
|
||||
getLocalWorldFavoriteGroupLength(group)
|
||||
}}</span>
|
||||
<el-tooltip placement="top" :content="$t('view.favorite.rename_tooltip')" :disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-edit"
|
||||
circle
|
||||
style="margin-left: 10px"
|
||||
@click.stop="promptLocalWorldFavoriteGroupRename(group)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
placement="right"
|
||||
:content="$t('view.favorite.delete_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-delete"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
@click.stop="promptLocalWorldFavoriteGroupDelete(group)" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<div v-if="localWorldFavorites[group].length" class="x-friend-list" style="margin-top: 10px">
|
||||
<favorites-world-item
|
||||
v-for="favorite in localWorldFavorites[group]"
|
||||
:key="favorite.id"
|
||||
is-local-favorite
|
||||
:group="group"
|
||||
:favorite="favorite"
|
||||
:edit-favorites-mode="editFavoritesMode"
|
||||
:hide-tooltips="hideTooltips"
|
||||
:shift-held="shiftHeld"
|
||||
@click="showWorldDialog(favorite.id)"
|
||||
@new-instance-self-invite="newInstanceSelfInvite"
|
||||
@remove-local-world-favorite="removeLocalWorldFavorite"
|
||||
@show-favorite-dialog="showFavoriteDialog" />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
style="
|
||||
padding-top: 25px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: rgb(144, 147, 153);
|
||||
">
|
||||
<span>No Data</span>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FavoritesWorldItem from './FavoritesWorldItem.vue';
|
||||
export default {
|
||||
name: 'FavoritesWorldTab',
|
||||
components: {
|
||||
FavoritesWorldItem
|
||||
},
|
||||
inject: ['API'],
|
||||
props: {
|
||||
sortFavorites: Boolean,
|
||||
worldFavoriteSearchResults: Array,
|
||||
|
||||
hideTooltips: Boolean,
|
||||
|
||||
favoriteWorlds: Array,
|
||||
|
||||
editFavoritesMode: Boolean,
|
||||
shiftHeld: Boolean,
|
||||
|
||||
refreshingLocalFavorites: Boolean,
|
||||
|
||||
localWorldFavoriteGroups: Array,
|
||||
localWorldFavorites: Object
|
||||
|
||||
// removeLocalWorldFavorite: Function
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
worldGroupVisibilityOptions: ['private', 'friends', 'public'],
|
||||
worldFavoriteSearch: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
groupedByGroupKeyFavoriteWorlds() {
|
||||
const groupedByGroupKeyFavoriteWorlds = {};
|
||||
|
||||
this.favoriteWorlds.forEach((world) => {
|
||||
if (world.groupKey) {
|
||||
if (!groupedByGroupKeyFavoriteWorlds[world.groupKey]) {
|
||||
groupedByGroupKeyFavoriteWorlds[world.groupKey] = [];
|
||||
}
|
||||
groupedByGroupKeyFavoriteWorlds[world.groupKey].push(world);
|
||||
}
|
||||
});
|
||||
|
||||
return groupedByGroupKeyFavoriteWorlds;
|
||||
},
|
||||
sortFav: {
|
||||
get() {
|
||||
return this.sortFavorites;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('update:sort-favorites', value);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
userFavoriteWorldsStatusForFavTab(visibility) {
|
||||
let style = '';
|
||||
if (visibility === 'public') {
|
||||
style = '';
|
||||
} else if (visibility === 'friends') {
|
||||
style = 'success';
|
||||
} else {
|
||||
style = 'info';
|
||||
}
|
||||
return style;
|
||||
},
|
||||
changeWorldGroupVisibility(name, visibility) {
|
||||
const params = {
|
||||
type: 'world',
|
||||
group: name,
|
||||
visibility
|
||||
};
|
||||
this.API.saveFavoriteGroup(params).then((args) => {
|
||||
this.$message({
|
||||
message: 'Group visibility changed',
|
||||
type: 'success'
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
promptNewLocalWorldFavoriteGroup() {
|
||||
this.$prompt(
|
||||
$t('prompt.new_local_favorite_group.description'),
|
||||
$t('prompt.new_local_favorite_group.header'),
|
||||
{
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: $t('prompt.new_local_favorite_group.ok'),
|
||||
cancelButtonText: $t('prompt.new_local_favorite_group.cancel'),
|
||||
inputPattern: /\S+/,
|
||||
inputErrorMessage: $t('prompt.new_local_favorite_group.input_error'),
|
||||
callback: (action, instance) => {
|
||||
if (action === 'confirm' && instance.inputValue) {
|
||||
this.newLocalWorldFavoriteGroup(instance.inputValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
promptLocalWorldFavoriteGroupRename(group) {
|
||||
this.$prompt(
|
||||
$t('prompt.local_favorite_group_rename.description'),
|
||||
$t('prompt.local_favorite_group_rename.header'),
|
||||
{
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: $t('prompt.local_favorite_group_rename.save'),
|
||||
cancelButtonText: $t('prompt.local_favorite_group_rename.cancel'),
|
||||
inputPattern: /\S+/,
|
||||
inputErrorMessage: $t('prompt.local_favorite_group_rename.input_error'),
|
||||
inputValue: group,
|
||||
callback: (action, instance) => {
|
||||
if (action === 'confirm' && instance.inputValue) {
|
||||
this.renameLocalWorldFavoriteGroup(instance.inputValue, group);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
promptLocalWorldFavoriteGroupDelete(group) {
|
||||
this.$confirm(`Delete Group? ${group}`, 'Confirm', {
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'info',
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this.deleteLocalWorldFavoriteGroup(group);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
searchWorldFavorites() {
|
||||
this.$emit('search-world-favorites', this.worldFavoriteSearch);
|
||||
},
|
||||
getLocalWorldFavoriteGroupLength(group) {
|
||||
const favoriteGroup = this.localWorldFavorites[group];
|
||||
if (!favoriteGroup) {
|
||||
return 0;
|
||||
}
|
||||
return favoriteGroup.length;
|
||||
},
|
||||
showWorldDialog(event) {
|
||||
this.$emit('show-world-dialog', event);
|
||||
},
|
||||
newInstanceSelfInvite(event) {
|
||||
this.$emit('new-instance-self-invite', event);
|
||||
},
|
||||
showFavoriteDialog(param1, param2) {
|
||||
this.$emit('show-favorite-dialog', param1, param2);
|
||||
},
|
||||
removeLocalWorldFavorite(param1, param2) {
|
||||
this.$emit('remove-local-world-favorite', param1, param2);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -318,9 +318,7 @@
|
||||
}
|
||||
},
|
||||
created() {
|
||||
configRepository.getBool('VRCX_sidebarGroupByInstanceCollapsed', false).then((value) => {
|
||||
this.isSidebarGroupByInstanceCollapsed = value;
|
||||
});
|
||||
this.loadFriendsGroupStates();
|
||||
},
|
||||
methods: {
|
||||
saveFriendsGroupStates() {
|
||||
@@ -336,6 +334,10 @@
|
||||
this.isOnlineFriends = await configRepository.getBool('VRCX_isFriendsGroupOnline', true);
|
||||
this.isActiveFriends = await configRepository.getBool('VRCX_isFriendsGroupActive', false);
|
||||
this.isOfflineFriends = await configRepository.getBool('VRCX_isFriendsGroupOffline', false);
|
||||
this.isSidebarGroupByInstanceCollapsed = await configRepository.getBool(
|
||||
'VRCX_sidebarGroupByInstanceCollapsed',
|
||||
false
|
||||
);
|
||||
},
|
||||
isRealInstance(locationTag) {
|
||||
return utils.isRealInstance(locationTag);
|
||||
|
||||
Reference in New Issue
Block a user