mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-11 10:53:52 +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:
240
src/app.js
240
src/app.js
@@ -51,8 +51,12 @@ import NavMenu from './views/NavMenu.vue';
|
||||
|
||||
// components
|
||||
import SimpleSwitch from './components/settings/SimpleSwitch.vue';
|
||||
import PreviousInstanceInfo from './views/dialogs/PreviousInstanceInfo.vue';
|
||||
import Location from './components/common/Location.vue';
|
||||
import FavoritesWorldTab from './components/favorites/FavoritesWorldTab.vue';
|
||||
|
||||
// dialogs
|
||||
import WorldDialog from './views/dialogs/WorldDialog.vue';
|
||||
import PreviousInstanceInfoDialog from './views/dialogs/PreviousInstanceInfoDialog.vue';
|
||||
|
||||
// main app classes
|
||||
import _sharedFeed from './classes/sharedFeed.js';
|
||||
@@ -189,15 +193,16 @@ console.log(`isLinux: ${LINUX}`);
|
||||
NavMenu,
|
||||
|
||||
// components
|
||||
// - common
|
||||
Location,
|
||||
// - favorites
|
||||
FavoritesWorldTab,
|
||||
// - settings
|
||||
SimpleSwitch,
|
||||
|
||||
// components
|
||||
// - common
|
||||
Location,
|
||||
|
||||
// - dialogs
|
||||
PreviousInstanceInfo
|
||||
PreviousInstanceInfoDialog,
|
||||
WorldDialog
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -206,7 +211,8 @@ console.log(`isLinux: ${LINUX}`);
|
||||
adjustDialogZ: this.adjustDialogZ,
|
||||
getWorldName: this.getWorldName,
|
||||
userImage: this.userImage,
|
||||
userStatusClass: this.userStatusClass
|
||||
userStatusClass: this.userStatusClass,
|
||||
getGroupName: this.getGroupName
|
||||
};
|
||||
},
|
||||
el: '#root',
|
||||
@@ -6096,25 +6102,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
}
|
||||
};
|
||||
|
||||
$app.methods.deleteFavorite = function (objectId) {
|
||||
API.deleteFavorite({
|
||||
objectId
|
||||
});
|
||||
// FIXME: 메시지 수정
|
||||
// this.$confirm('Continue? Delete Favorite', 'Confirm', {
|
||||
// confirmButtonText: 'Confirm',
|
||||
// cancelButtonText: 'Cancel',
|
||||
// type: 'info',
|
||||
// callback: (action) => {
|
||||
// if (action === 'confirm') {
|
||||
// API.deleteFavorite({
|
||||
// objectId
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
};
|
||||
|
||||
$app.methods.deleteFavoriteNoConfirm = function (objectId) {
|
||||
if (!objectId) {
|
||||
return;
|
||||
@@ -6185,21 +6172,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
return this.favoriteWorldsSorted;
|
||||
};
|
||||
|
||||
$app.computed.groupedByGroupKeyFavoriteWorlds = function () {
|
||||
const groupedByGroupKeyFavoriteWorlds = {};
|
||||
|
||||
this.favoriteWorlds.forEach((world) => {
|
||||
if (world.groupKey) {
|
||||
if (!groupedByGroupKeyFavoriteWorlds[world.groupKey]) {
|
||||
groupedByGroupKeyFavoriteWorlds[world.groupKey] = [];
|
||||
}
|
||||
groupedByGroupKeyFavoriteWorlds[world.groupKey].push(world);
|
||||
}
|
||||
});
|
||||
|
||||
return groupedByGroupKeyFavoriteWorlds;
|
||||
};
|
||||
|
||||
$app.computed.favoriteAvatars = function () {
|
||||
if (this.sortFavoriteAvatars) {
|
||||
this.sortFavoriteAvatars = false;
|
||||
@@ -10576,9 +10548,8 @@ console.log(`isLinux: ${LINUX}`);
|
||||
});
|
||||
|
||||
$app.methods.showWorldDialog = function (tag, shortName) {
|
||||
this.$nextTick(() => $app.adjustDialogZ(this.$refs.worldDialog.$el));
|
||||
var D = this.worldDialog;
|
||||
var L = $utils.parseLocation(tag);
|
||||
const D = this.worldDialog;
|
||||
const L = $utils.parseLocation(tag);
|
||||
if (L.worldId === '') {
|
||||
return;
|
||||
}
|
||||
@@ -11049,9 +11020,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
case 'Refresh':
|
||||
this.showWorldDialog(D.id);
|
||||
break;
|
||||
case 'Share':
|
||||
this.copyWorldUrl(D.id);
|
||||
break;
|
||||
case 'New Instance':
|
||||
this.showNewInstanceDialog(D.$location.tag);
|
||||
break;
|
||||
@@ -11209,30 +11177,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.refreshWorldDialogTreeData = function () {
|
||||
var D = this.worldDialog;
|
||||
D.treeData = $utils.buildTreeData(D.ref);
|
||||
};
|
||||
|
||||
$app.computed.worldDialogPlatform = function () {
|
||||
var { ref } = this.worldDialog;
|
||||
var platforms = [];
|
||||
if (ref.unityPackages) {
|
||||
for (var unityPackage of ref.unityPackages) {
|
||||
var platform = 'PC';
|
||||
if (unityPackage.platform === 'standalonewindows') {
|
||||
platform = 'PC';
|
||||
} else if (unityPackage.platform === 'android') {
|
||||
platform = 'Android';
|
||||
} else if (unityPackage.platform) {
|
||||
({ platform } = unityPackage);
|
||||
}
|
||||
platforms.unshift(`${platform}/${unityPackage.unityVersion}`);
|
||||
}
|
||||
}
|
||||
return platforms.join(', ');
|
||||
};
|
||||
|
||||
// #endregion
|
||||
// #region | App: Avatar Dialog
|
||||
|
||||
@@ -11805,18 +11749,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.moveFavorite = function (ref, group, type) {
|
||||
API.deleteFavorite({
|
||||
objectId: ref.id
|
||||
}).then(() => {
|
||||
API.addFavorite({
|
||||
type,
|
||||
favoriteId: ref.id,
|
||||
tags: group.name
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.showFavoriteDialog = function (type, objectId) {
|
||||
this.$nextTick(() => $app.adjustDialogZ(this.$refs.favoriteDialog.$el));
|
||||
var D = this.favoriteDialog;
|
||||
@@ -13264,30 +13196,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.copyToClipboard(`https://vrchat.com/home/avatar/${avatarId}`);
|
||||
};
|
||||
|
||||
$app.methods.copyWorldId = function (worldId) {
|
||||
this.$message({
|
||||
message: 'World ID copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
this.copyToClipboard(worldId);
|
||||
};
|
||||
|
||||
$app.methods.copyWorldUrl = function (worldId) {
|
||||
this.$message({
|
||||
message: 'World URL copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
this.copyToClipboard(`https://vrchat.com/home/world/${worldId}`);
|
||||
};
|
||||
|
||||
$app.methods.copyWorldName = function (worldName) {
|
||||
this.$message({
|
||||
message: 'World name copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
this.copyToClipboard(worldName);
|
||||
};
|
||||
|
||||
$app.methods.copyUserId = function (userId) {
|
||||
this.$message({
|
||||
message: 'User ID copied to clipboard',
|
||||
@@ -16829,8 +16737,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.userDialog.isFavoriteWorldsLoading = false;
|
||||
};
|
||||
|
||||
$app.data.worldGroupVisibilityOptions = ['private', 'friends', 'public'];
|
||||
|
||||
$app.methods.userFavoriteWorldsStatus = function (visibility) {
|
||||
var style = {};
|
||||
if (visibility === 'public') {
|
||||
@@ -16843,33 +16749,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
return style;
|
||||
};
|
||||
|
||||
$app.methods.userFavoriteWorldsStatusForFavTab = function (visibility) {
|
||||
let style = '';
|
||||
if (visibility === 'public') {
|
||||
style = '';
|
||||
} else if (visibility === 'friends') {
|
||||
style = 'success';
|
||||
} else {
|
||||
style = 'info';
|
||||
}
|
||||
return style;
|
||||
};
|
||||
|
||||
$app.methods.changeWorldGroupVisibility = function (name, visibility) {
|
||||
var params = {
|
||||
type: 'world',
|
||||
group: name,
|
||||
visibility
|
||||
};
|
||||
API.saveFavoriteGroup(params).then((args) => {
|
||||
this.$message({
|
||||
message: 'Group visibility changed',
|
||||
type: 'success'
|
||||
});
|
||||
return args;
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.refreshInstancePlayerCount = function (instance) {
|
||||
var L = $utils.parseLocation(instance);
|
||||
if (L.isRealInstance) {
|
||||
@@ -20545,27 +20424,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
return favoriteGroup.length;
|
||||
};
|
||||
|
||||
$app.methods.promptNewLocalWorldFavoriteGroup = function () {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$app.methods.newLocalWorldFavoriteGroup = function (group) {
|
||||
if (this.localWorldFavoriteGroups.includes(group)) {
|
||||
$app.$message({
|
||||
@@ -20585,35 +20443,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.sortLocalWorldFavorites();
|
||||
};
|
||||
|
||||
$app.methods.promptLocalWorldFavoriteGroupRename = function (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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$app.methods.renameLocalWorldFavoriteGroup = function (newName, group) {
|
||||
if (this.localWorldFavoriteGroups.includes(newName)) {
|
||||
$app.$message({
|
||||
@@ -20634,19 +20463,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.sortLocalWorldFavorites();
|
||||
};
|
||||
|
||||
$app.methods.promptLocalWorldFavoriteGroupDelete = function (group) {
|
||||
this.$confirm(`Delete Group? ${group}`, 'Confirm', {
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'info',
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this.deleteLocalWorldFavoriteGroup(group);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.sortLocalWorldFavorites = function () {
|
||||
this.localWorldFavoriteGroups.sort();
|
||||
if (!this.sortFavorites) {
|
||||
@@ -20729,11 +20545,10 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.refreshingLocalFavorites = false;
|
||||
};
|
||||
|
||||
$app.data.worldFavoriteSearch = '';
|
||||
$app.data.worldFavoriteSearchResults = [];
|
||||
|
||||
$app.methods.searchWorldFavorites = function () {
|
||||
var search = this.worldFavoriteSearch.toLowerCase();
|
||||
$app.methods.searchWorldFavorites = function (worldFavoriteSearch) {
|
||||
var search = worldFavoriteSearch.toLowerCase();
|
||||
if (search.length < 3) {
|
||||
this.worldFavoriteSearchResults = [];
|
||||
return;
|
||||
@@ -22447,27 +22262,6 @@ console.log(`isLinux: ${LINUX}`);
|
||||
);
|
||||
};
|
||||
|
||||
// favorites Tab
|
||||
// - local favorites
|
||||
// - local world & avatar
|
||||
$app.data.localFavoriteShowDelayedContent = [false, false];
|
||||
|
||||
$app.methods.onFavTabClick = function (el) {
|
||||
if (el.index === '0') {
|
||||
this.localFavoriteShowDelayedContent = [false, false];
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (el.index === '1') {
|
||||
this.localFavoriteShowDelayedContent = [true, false];
|
||||
} else if (el.index === '2') {
|
||||
this.localFavoriteShowDelayedContent = [false, true];
|
||||
}
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region | Tab Props
|
||||
|
||||
@@ -84,11 +84,6 @@ export default class extends baseClass {
|
||||
});
|
||||
},
|
||||
|
||||
onWorldMemoChange() {
|
||||
var D = this.worldDialog;
|
||||
this.saveWorldMemo(D.id, D.memo);
|
||||
},
|
||||
|
||||
async getWorldMemo(worldId) {
|
||||
try {
|
||||
return await database.getWorldMemo(worldId);
|
||||
@@ -102,18 +97,6 @@ export default class extends baseClass {
|
||||
}
|
||||
},
|
||||
|
||||
saveWorldMemo(worldId, memo) {
|
||||
if (memo) {
|
||||
database.setWorldMemo({
|
||||
worldId,
|
||||
editedAt: new Date().toJSON(),
|
||||
memo
|
||||
});
|
||||
} else {
|
||||
database.deleteWorldMemo(worldId);
|
||||
}
|
||||
},
|
||||
|
||||
onAvatarMemoChange() {
|
||||
var D = this.avatarDialog;
|
||||
this.saveAvatarMemo(D.id, D.memo);
|
||||
|
||||
@@ -294,6 +294,7 @@ export default class extends baseClass {
|
||||
);
|
||||
},
|
||||
|
||||
// remove when finished fav tab split
|
||||
changeFavoriteGroupName(ctx) {
|
||||
this.$prompt(
|
||||
$t('prompt.change_favorite_group_name.description'),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -123,7 +123,7 @@ mixin previousInstances
|
||||
size='mini'
|
||||
@click='deleteGameLogWorldInstancePrompt(scope.row)')
|
||||
|
||||
previous-instance-info(
|
||||
previous-instance-info-dialog(
|
||||
:visible.sync='previousInstanceInfoDialogVisible'
|
||||
:instance-id='previousInstanceInfoDialogInstanceId'
|
||||
:game-log-is-friend='gameLogIsFriend'
|
||||
|
||||
@@ -1,453 +1,20 @@
|
||||
mixin worldDialog
|
||||
el-dialog.x-dialog.x-world-dialog(
|
||||
:before-close='beforeDialogClose'
|
||||
@mousedown.native='dialogMouseDown'
|
||||
@mouseup.native='dialogMouseUp'
|
||||
ref='worldDialog'
|
||||
:visible.sync='worldDialog.visible'
|
||||
:show-close='false'
|
||||
width='770px')
|
||||
div(v-loading='worldDialog.loading')
|
||||
div(style='display: flex')
|
||||
el-popover(placement='right' width='500px' trigger='click')
|
||||
img.x-link(
|
||||
slot='reference'
|
||||
v-lazy='worldDialog.ref.thumbnailImageUrl'
|
||||
style='flex: none; width: 160px; height: 120px; border-radius: 12px')
|
||||
img.x-link(
|
||||
v-lazy='worldDialog.ref.imageUrl'
|
||||
style='width: 500px; height: 375px'
|
||||
@click='showFullscreenImageDialog(worldDialog.ref.imageUrl)')
|
||||
div(style='flex: 1; display: flex; align-items: center; margin-left: 15px')
|
||||
div(style='flex: 1')
|
||||
div
|
||||
i.el-icon-s-home(
|
||||
v-show='API.currentUser.$homeLocation && API.currentUser.$homeLocation.worldId === worldDialog.id'
|
||||
style='margin-right: 5px')
|
||||
span.dialog-title(v-text='worldDialog.ref.name')
|
||||
div(style='margin-top: 5px')
|
||||
span.x-link.x-grey(
|
||||
v-text='worldDialog.ref.authorName'
|
||||
@click='showUserDialog(worldDialog.ref.authorId)'
|
||||
style='font-family: monospace')
|
||||
div
|
||||
el-tag(
|
||||
v-if='worldDialog.ref.$isLabs'
|
||||
type='primary'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.world.tags.labs') }}
|
||||
el-tag(
|
||||
v-else-if='worldDialog.ref.releaseStatus === "public"'
|
||||
type='success'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.world.tags.public') }}
|
||||
el-tag(
|
||||
v-else
|
||||
type='danger'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.world.tags.private') }}
|
||||
el-tag.x-tag-platform-pc(
|
||||
v-if='worldDialog.isPC'
|
||||
type='info'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') PC
|
||||
span.x-grey(
|
||||
v-if='worldDialog.bundleSizes["standalonewindows"]'
|
||||
style='margin-left: 5px; border-left: inherit; padding-left: 5px') {{ worldDialog.bundleSizes['standalonewindows'].fileSize }}
|
||||
el-tag.x-tag-platform-quest(
|
||||
v-if='worldDialog.isQuest'
|
||||
type='info'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') Android
|
||||
span.x-grey(
|
||||
v-if='worldDialog.bundleSizes["android"]'
|
||||
style='margin-left: 5px; border-left: inherit; padding-left: 5px') {{ worldDialog.bundleSizes['android'].fileSize }}
|
||||
el-tag.x-tag-platform-ios(
|
||||
v-if='worldDialog.isIos'
|
||||
type='info'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') iOS
|
||||
span.x-grey(
|
||||
v-if='worldDialog.bundleSizes["ios"]'
|
||||
style='margin-left: 5px; border-left: inherit; padding-left: 5px') {{ worldDialog.bundleSizes['ios'].fileSize }}
|
||||
el-tag(
|
||||
v-if='worldDialog.avatarScalingDisabled'
|
||||
type='warning'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.world.tags.avatar_scaling_disabled') }}
|
||||
el-tag(
|
||||
v-if='worldDialog.focusViewDisabled'
|
||||
type='warning'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.world.tags.focus_view_disabled') }}
|
||||
el-tag(
|
||||
v-if='worldDialog.stickersDisabled'
|
||||
type='warning'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.world.tags.stickers_disabled') }}
|
||||
el-tag(
|
||||
v-if='worldDialog.ref.unityPackageUrl'
|
||||
type='success'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.world.tags.future_proofing') }}
|
||||
el-tag.x-link(
|
||||
v-if='worldDialog.inCache'
|
||||
type='info'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px'
|
||||
@click='openFolderGeneric(worldDialog.cachePath)')
|
||||
span(v-text='worldDialog.cacheSize')
|
||||
| {{ $t('dialog.world.tags.cache') }}
|
||||
div
|
||||
template(v-for='tag in worldDialog.ref.tags')
|
||||
el-tag(
|
||||
v-if='tag.startsWith("content_")'
|
||||
:key='tag'
|
||||
effect='plain'
|
||||
size='mini'
|
||||
style='margin-right: 5px; margin-top: 5px')
|
||||
template(v-if='tag === "content_horror"') {{ $t('dialog.world.tags.content_horror') }}
|
||||
template(v-else-if='tag === "content_gore"') {{ $t('dialog.world.tags.content_gore') }}
|
||||
template(v-else-if='tag === "content_violence"') {{ $t('dialog.world.tags.content_violence') }}
|
||||
template(v-else-if='tag === "content_adult"') {{ $t('dialog.world.tags.content_adult') }}
|
||||
template(v-else-if='tag === "content_sex"') {{ $t('dialog.world.tags.content_sex') }}
|
||||
template(v-else) {{ tag.replace('content_', '') }}
|
||||
div(style='margin-top: 5px')
|
||||
span(
|
||||
v-show='worldDialog.ref.name !== worldDialog.ref.description'
|
||||
v-text='worldDialog.ref.description'
|
||||
style='font-size: 12px')
|
||||
div(style='flex: none; margin-left: 10px')
|
||||
el-tooltip(
|
||||
v-if='worldDialog.inCache'
|
||||
placement='top'
|
||||
:content='$t("dialog.world.actions.delete_cache_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
icon='el-icon-delete'
|
||||
circle
|
||||
@click='deleteVRChatCache(worldDialog.ref)'
|
||||
:disabled='isGameRunning && worldDialog.cacheLocked')
|
||||
el-tooltip(
|
||||
v-if='worldDialog.isFavorite'
|
||||
placement='top'
|
||||
:content='$t("dialog.world.actions.favorites_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
type='default'
|
||||
icon='el-icon-star-on'
|
||||
circle
|
||||
@click='worldDialogCommand("Add Favorite")'
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
v-else
|
||||
placement='top'
|
||||
:content='$t("dialog.world.actions.favorites_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
type='default'
|
||||
icon='el-icon-star-off'
|
||||
circle
|
||||
@click='worldDialogCommand("Add Favorite")'
|
||||
style='margin-left: 5px')
|
||||
el-dropdown(
|
||||
trigger='click'
|
||||
@command='worldDialogCommand'
|
||||
size='small'
|
||||
style='margin-left: 5px')
|
||||
el-button(type='default' icon='el-icon-more' circle)
|
||||
el-dropdown-menu(#default='dropdown')
|
||||
el-dropdown-item(icon='el-icon-refresh' command='Refresh') {{ $t('dialog.world.actions.refresh') }}
|
||||
el-dropdown-item(icon='el-icon-share' command='Share') {{ $t('dialog.world.actions.share') }}
|
||||
el-dropdown-item(icon='el-icon-s-flag' command='New Instance' divided) {{ $t('dialog.world.actions.new_instance') }}
|
||||
el-dropdown-item(icon='el-icon-message' command='New Instance and Self Invite') {{ $t('dialog.world.actions.new_instance_and_self_invite') }}
|
||||
el-dropdown-item(
|
||||
v-if='API.currentUser.$homeLocation && API.currentUser.$homeLocation.worldId === worldDialog.id'
|
||||
icon='el-icon-magic-stick'
|
||||
command='Reset Home'
|
||||
divided) {{ $t('dialog.world.actions.reset_home') }}
|
||||
el-dropdown-item(v-else icon='el-icon-s-home' command='Make Home' divided) {{ $t('dialog.world.actions.make_home') }}
|
||||
el-dropdown-item(icon='el-icon-tickets' command='Previous Instances') {{ $t('dialog.world.actions.show_previous_instances') }}
|
||||
template(v-if='API.currentUser.id !== worldDialog.ref.authorId')
|
||||
el-dropdown-item(icon='el-icon-picture-outline' command='Previous Images') {{ $t('dialog.world.actions.show_previous_images') }}
|
||||
el-dropdown-item(
|
||||
:disabled='!worldDialog.hasPersistData'
|
||||
icon='el-icon-upload'
|
||||
command='Delete Persistent Data') {{ $t('dialog.world.actions.delete_persistent_data') }}
|
||||
template(v-else)
|
||||
el-dropdown-item(icon='el-icon-edit' command='Rename') {{ $t('dialog.world.actions.rename') }}
|
||||
el-dropdown-item(icon='el-icon-edit' command='Change Description') {{ $t('dialog.world.actions.change_description') }}
|
||||
el-dropdown-item(icon='el-icon-edit' command='Change Capacity') {{ $t('dialog.world.actions.change_capacity') }}
|
||||
el-dropdown-item(icon='el-icon-edit' command='Change Recommended Capacity') {{ $t('dialog.world.actions.change_recommended_capacity') }}
|
||||
el-dropdown-item(icon='el-icon-edit' command='Change YouTube Preview') {{ $t('dialog.world.actions.change_preview') }}
|
||||
el-dropdown-item(icon='el-icon-edit' command='Change Tags') {{ $t('dialog.world.actions.change_tags') }}
|
||||
el-dropdown-item(icon='el-icon-edit' command='Change Allowed Domains') {{ $t('dialog.world.actions.change_allowed_video_player_domains') }}
|
||||
el-dropdown-item(icon='el-icon-picture-outline' command='Change Image') {{ $t('dialog.world.actions.change_image') }}
|
||||
el-dropdown-item(
|
||||
v-if='worldDialog.ref.unityPackageUrl'
|
||||
icon='el-icon-download'
|
||||
command='Download Unity Package') {{ $t('dialog.world.actions.download_package') }}
|
||||
el-dropdown-item(
|
||||
v-if='worldDialog.ref.tags.includes("system_approved") || worldDialog.ref.tags.includes("system_labs")'
|
||||
icon='el-icon-view'
|
||||
command='Unpublish'
|
||||
divided) {{ $t('dialog.world.actions.unpublish') }}
|
||||
el-dropdown-item(v-else icon='el-icon-view' command='Publish' divided) {{ $t('dialog.world.actions.publish_to_labs') }}
|
||||
el-dropdown-item(
|
||||
:disabled='!worldDialog.hasPersistData'
|
||||
icon='el-icon-upload'
|
||||
command='Delete Persistent Data') {{ $t('dialog.world.actions.delete_persistent_data') }}
|
||||
el-dropdown-item(icon='el-icon-delete' command='Delete' style='color: #f56c6c') {{ $t('dialog.world.actions.delete') }}
|
||||
el-tabs
|
||||
el-tab-pane(:label='$t("dialog.world.instances.header")')
|
||||
div.
|
||||
#[i.el-icon-user] {{ $t('dialog.world.instances.public_count', { count: worldDialog.ref.publicOccupants }) }}
|
||||
#[i.el-icon-user-solid(style='margin-left: 10px')] {{ $t('dialog.world.instances.private_count', { count: worldDialog.ref.privateOccupants }) }}
|
||||
#[i.el-icon-check(style='margin-left: 10px')] {{ $t('dialog.world.instances.capacity_count', { count: worldDialog.ref.recommendedCapacity, max: worldDialog.ref.capacity }) }}
|
||||
div(v-for='room in worldDialog.rooms' :key='room.id')
|
||||
div(style='margin: 5px 0')
|
||||
location-world(
|
||||
:locationobject='room.$location'
|
||||
:currentuserid='API.currentUser.id'
|
||||
:worlddialogshortname='worldDialog.$location.shortName'
|
||||
@show-launch-dialog='showLaunchDialog')
|
||||
launch(
|
||||
:location='room.tag'
|
||||
@show-launch-dialog='showLaunchDialog'
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='top'
|
||||
:content='$t("dialog.world.instances.self_invite_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
invite-yourself(
|
||||
:location='room.$location.tag'
|
||||
:shortname='room.$location.shortName'
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='top'
|
||||
:content='$t("dialog.world.instances.refresh_instance_info")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click='refreshInstancePlayerCount(room.tag)'
|
||||
size='mini'
|
||||
icon='el-icon-refresh'
|
||||
style='margin-left: 5px'
|
||||
circle)
|
||||
el-tooltip(
|
||||
v-if='instanceJoinHistory.get(room.$location.tag)'
|
||||
placement='top'
|
||||
:content='$t("dialog.previous_instances.info")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click='showPreviousInstanceInfoDialog(room.location)'
|
||||
size='mini'
|
||||
icon='el-icon-s-data'
|
||||
style='margin-left: 5px'
|
||||
plain
|
||||
circle)
|
||||
last-join(:location='room.$location.tag' :currentlocation='lastLocation.location')
|
||||
instance-info(
|
||||
:location='room.tag'
|
||||
:instance='room.ref'
|
||||
:friendcount='room.friendCount'
|
||||
:updateelement='updateInstanceInfo')
|
||||
.x-friend-list(
|
||||
style='margin: 10px 0; max-height: unset'
|
||||
v-if='room.$location.userId || room.users.length')
|
||||
.x-friend-item.x-friend-item-border(
|
||||
v-if='room.$location.userId'
|
||||
@click='showUserDialog(room.$location.userId)')
|
||||
template(v-if='room.$location.user')
|
||||
.avatar(:class='userStatusClass(room.$location.user)')
|
||||
img(v-lazy='userImage(room.$location.user)')
|
||||
.detail
|
||||
span.name(
|
||||
v-text='room.$location.user.displayName'
|
||||
:style='{ color: room.$location.user.$userColour }')
|
||||
span.extra {{ $t('dialog.world.instances.instance_creator') }}
|
||||
span(v-else v-text='room.$location.userId')
|
||||
.x-friend-item.x-friend-item-border(
|
||||
v-for='user in room.users'
|
||||
:key='user.id'
|
||||
@click='showUserDialog(user.id)')
|
||||
.avatar(:class='userStatusClass(user)')
|
||||
img(v-lazy='userImage(user)')
|
||||
.detail
|
||||
span.name(v-text='user.displayName' :style='{ color: user.$userColour }')
|
||||
span.extra(v-if='user.location === "traveling"')
|
||||
i.el-icon-loading(style='margin-right: 5px')
|
||||
timer(:epoch='user.$travelingToTime')
|
||||
span.extra(v-else)
|
||||
timer(:epoch='user.$location_at')
|
||||
el-tab-pane(:label='$t("dialog.world.info.header")' lazy)
|
||||
.x-friend-list(style='max-height: none')
|
||||
.x-friend-item(style='width: 100%; cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.memo') }}
|
||||
el-input.extra(
|
||||
v-model='worldDialog.memo'
|
||||
@change='onWorldMemoChange'
|
||||
type='textarea'
|
||||
:rows='2'
|
||||
:autosize='{ minRows: 1, maxRows: 20 }'
|
||||
:placeholder='$t("dialog.world.info.memo_placeholder")'
|
||||
size='mini'
|
||||
resize='none')
|
||||
div(style='width: 100%; display: flex')
|
||||
.x-friend-item(style='width: 100%; cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.id') }}
|
||||
span.extra {{ worldDialog.id }}
|
||||
el-tooltip(
|
||||
placement='top'
|
||||
:content='$t("dialog.world.info.id_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-dropdown(
|
||||
trigger='click'
|
||||
@click.native.stop
|
||||
size='mini'
|
||||
style='margin-left: 5px')
|
||||
el-button(type='default' icon='el-icon-s-order' size='mini' circle)
|
||||
el-dropdown-menu(#default='dropdown')
|
||||
el-dropdown-item(@click.native='copyWorldId(worldDialog.id)') {{ $t('dialog.world.info.copy_id') }}
|
||||
el-dropdown-item(@click.native='copyWorldUrl(worldDialog.id)') {{ $t('dialog.world.info.copy_url') }}
|
||||
el-dropdown-item(
|
||||
@click.native='copyWorldName(worldDialog.ref.name)') {{ $t('dialog.world.info.copy_name') }}
|
||||
.x-friend-item(
|
||||
v-if='worldDialog.ref.previewYoutubeId'
|
||||
style='width: 350px'
|
||||
@click='openExternalLink(`https://www.youtube.com/watch?v=${worldDialog.ref.previewYoutubeId}`)')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.youtube_preview') }}
|
||||
span.extra https://www.youtube.com/watch?v={{ worldDialog.ref.previewYoutubeId }}
|
||||
.x-friend-item(style='width: 100%; cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.author_tags') }}
|
||||
span.extra(
|
||||
v-if='worldDialog.ref.tags?.filter((tag) => tag.startsWith("author_tag")).length > 0') {{ worldDialog.ref.tags.filter((tag) => tag.startsWith('author_tag')).map((tag) => tag.replace('author_tag_', '')).join(', ') }}
|
||||
span.extra(v-else) -
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.players') }}
|
||||
span.extra {{ worldDialog.ref.occupants | commaNumber }}
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.favorites') }}
|
||||
span.extra {{ worldDialog.ref.favorites | commaNumber }}
|
||||
| #[span.extra(v-if='worldDialog.ref.favorites > 0 && worldDialog.ref.visits > 0') ({{ Math.round((((worldDialog.ref.favorites - worldDialog.ref.visits) / worldDialog.ref.visits) * 100 + 100) * 100) / 100 }}%)]
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.visits') }}
|
||||
span.extra {{ worldDialog.ref.visits | commaNumber }}
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.capacity') }}
|
||||
span.extra {{ worldDialog.ref.recommendedCapacity | commaNumber }} ({{ worldDialog.ref.capacity | commaNumber }})
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.created_at') }}
|
||||
span.extra {{ worldDialog.ref.created_at | formatDate('long') }}
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.last_updated') }}
|
||||
span.extra(v-if='worldDialog.lastUpdated') {{ worldDialog.lastUpdated | formatDate('long') }}
|
||||
span.extra(v-else) {{ worldDialog.ref.updated_at | formatDate('long') }}
|
||||
.x-friend-item(v-if='worldDialog.ref.labsPublicationDate !== "none"' style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.labs_publication_date') }}
|
||||
span.extra {{ worldDialog.ref.labsPublicationDate | formatDate('long') }}
|
||||
.x-friend-item(v-if='worldDialog.ref.publicationDate !== "none"' style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.publication_date') }}
|
||||
el-tooltip(
|
||||
v-if='worldDialog.ref.publicationDate && worldDialog.ref.publicationDate !== "none" && worldDialog.ref.labsPublicationDate && worldDialog.ref.labsPublicationDate !== "none"'
|
||||
placement='top'
|
||||
style='margin-left: 5px')
|
||||
template(#content)
|
||||
span {{ $t('dialog.world.info.time_in_labs') }} {{ timeToText(new Date(worldDialog.ref.publicationDate) - new Date(worldDialog.ref.labsPublicationDate)) }}
|
||||
i.el-icon-arrow-down
|
||||
span.extra {{ worldDialog.ref.publicationDate | formatDate('long') }}
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.version') }}
|
||||
span.extra(v-text='worldDialog.ref.version')
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.heat') }}
|
||||
span.extra {{ worldDialog.ref.heat | commaNumber }} {{ '🔥'.repeat(worldDialog.ref.heat) }}
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.popularity') }}
|
||||
span.extra {{ worldDialog.ref.popularity | commaNumber }} {{ '💖'.repeat(worldDialog.ref.popularity) }}
|
||||
.x-friend-item(style='width: 100%; cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.platform') }}
|
||||
span.extra(v-text='worldDialogPlatform')
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.last_visited') }}
|
||||
el-tooltip(
|
||||
v-if='!hideTooltips'
|
||||
placement='top'
|
||||
style='margin-left: 5px'
|
||||
:content='$t("dialog.world.info.accuracy_notice")')
|
||||
i.el-icon-warning
|
||||
span.extra {{ worldDialog.lastVisit | formatDate('long') }}
|
||||
el-tooltip(
|
||||
:disabled='hideTooltips'
|
||||
placement='top'
|
||||
:content='$t("dialog.user.info.open_previouse_instance")')
|
||||
.x-friend-item(@click='showPreviousInstancesWorldDialog(worldDialog.ref)')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.visit_count') }}
|
||||
el-tooltip(
|
||||
v-if='!hideTooltips'
|
||||
placement='top'
|
||||
style='margin-left: 5px'
|
||||
:content='$t("dialog.world.info.accuracy_notice")')
|
||||
i.el-icon-warning
|
||||
span.extra(v-text='worldDialog.visitCount')
|
||||
.x-friend-item(style='cursor: default')
|
||||
.detail
|
||||
span.name {{ $t('dialog.world.info.time_spent') }}
|
||||
el-tooltip(
|
||||
v-if='!hideTooltips'
|
||||
placement='top'
|
||||
style='margin-left: 5px'
|
||||
:content='$t("dialog.world.info.accuracy_notice")')
|
||||
i.el-icon-warning
|
||||
span.extra(v-if='worldDialog.timeSpent === 0') -
|
||||
span.extra(v-else) {{ timeToText(worldDialog.timeSpent) }}
|
||||
el-tab-pane(:label='$t("dialog.world.json.header")' lazy)
|
||||
el-button(
|
||||
type='default'
|
||||
@click='refreshWorldDialogTreeData()'
|
||||
size='mini'
|
||||
icon='el-icon-refresh'
|
||||
circle)
|
||||
el-button(
|
||||
type='default'
|
||||
@click='downloadAndSaveJson(worldDialog.id, worldDialog.ref)'
|
||||
size='mini'
|
||||
icon='el-icon-download'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
el-tree(:data='worldDialog.treeData' style='margin-top: 5px; font-size: 12px')
|
||||
template(#default='scope')
|
||||
span
|
||||
span(v-text='scope.data.key' style='font-weight: bold; margin-right: 5px')
|
||||
span(v-if='!scope.data.children' v-text='scope.data.value')
|
||||
world-dialog(
|
||||
:world-dialog='worldDialog'
|
||||
:hide-tooltips='hideTooltips'
|
||||
:is-game-running='isGameRunning'
|
||||
:last-location='lastLocation'
|
||||
:instance-join-history='instanceJoinHistory'
|
||||
:update-instance-info='updateInstanceInfo'
|
||||
@show-fullscreen-image-dialog='showFullscreenImageDialog'
|
||||
@open-folder-generic='openFolderGeneric'
|
||||
@delete-vrchat-cache='deleteVRChatCache'
|
||||
@world-dialog-command='worldDialogCommand'
|
||||
@show-launch-dialog='showLaunchDialog'
|
||||
@refresh-instance-player-count='refreshInstancePlayerCount'
|
||||
@show-previous-instance-info-dialog='showPreviousInstanceInfoDialog'
|
||||
@show-previous-instances-world-dialog='showPreviousInstancesWorldDialog'
|
||||
@download-and-save-json='downloadAndSaveJson')
|
||||
|
||||
//- dialog: change Allowed Video Player Domains
|
||||
el-dialog.x-dialog(
|
||||
|
||||
@@ -16,7 +16,7 @@ mixin favoritesTab
|
||||
size='small'
|
||||
icon='el-icon-refresh'
|
||||
circle)
|
||||
el-tabs(type='card' v-loading='API.isFavoriteLoading' style='height: 100%' @tab-click='onFavTabClick')
|
||||
el-tabs(type='card' v-loading='API.isFavoriteLoading' style='height: 100%')
|
||||
el-tab-pane(:label='$t("view.favorite.friends.header")' lazy)
|
||||
div(style='display: flex; align-items: center; justify-content: space-between')
|
||||
div
|
||||
@@ -132,302 +132,28 @@ mixin favoritesTab
|
||||
style='padding-top: 25px; width: 100%; display: flex; align-items: center; justify-content: center; color: rgb(144, 147, 153)')
|
||||
span No Data
|
||||
el-tab-pane(:label='$t("view.favorite.worlds.header")' lazy)
|
||||
div(style='display: flex; align-items: center; justify-content: space-between')
|
||||
div
|
||||
el-button(size='small' @click='showWorldExportDialog') {{ $t('view.favorite.export') }}
|
||||
el-button(size='small' @click='showWorldImportDialog' style='margin-left: 5px') {{ $t('view.favorite.import') }}
|
||||
div(style='display: flex; align-items: center; font-size: 13px; margin-right: 10px')
|
||||
span.name(style='margin-right: 5px; line-height: 10px') {{ $t('view.favorite.sort_by') }}
|
||||
el-radio-group(
|
||||
v-model='sortFavorites'
|
||||
@change='saveSortFavoritesOption'
|
||||
style='margin-right: 12px')
|
||||
el-radio(:label='false') {{ $t('view.settings.appearance.appearance.sort_favorite_by_name') }}
|
||||
el-radio(:label='true') {{ $t('view.settings.appearance.appearance.sort_favorite_by_date') }}
|
||||
el-input(
|
||||
v-model='worldFavoriteSearch'
|
||||
@input='searchWorldFavorites'
|
||||
clearable
|
||||
size='mini'
|
||||
:placeholder='$t("view.favorite.worlds.search")'
|
||||
style='width: 200px')
|
||||
.x-friend-list(style='margin-top: 10px')
|
||||
div(
|
||||
style='display: inline-block; width: 300px; margin-right: 15px'
|
||||
v-for='favorite in worldFavoriteSearchResults'
|
||||
:key='favorite.id'
|
||||
@click='showWorldDialog(favorite.id)')
|
||||
.x-friend-item
|
||||
template(v-if='favorite.name')
|
||||
.avatar
|
||||
img(v-lazy='favorite.thumbnailImageUrl')
|
||||
.detail
|
||||
span.name(v-text='favorite.name')
|
||||
span.extra(v-if='favorite.occupants') {{ favorite.authorName }} ({{ favorite.occupants }})
|
||||
span.extra(v-else v-text='favorite.authorName')
|
||||
template(v-else)
|
||||
.avatar
|
||||
.detail
|
||||
span(v-text='favorite.id')
|
||||
span(style='display: block; margin-top: 20px') {{ $t('view.favorite.worlds.vrchat_favorites') }}
|
||||
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(
|
||||
v-text='group.displayName'
|
||||
style='font-weight: bold; font-size: 14px; margin-left: 10px')
|
||||
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) }}
|
||||
span(style='color: #909399; font-size: 12px; margin-left: 10px') {{ group.count }}/{{ group.capacity }}
|
||||
el-dropdown(trigger='click' @click.native.stop size='mini' style='margin-left: 10px')
|
||||
el-tooltip(
|
||||
placement='top'
|
||||
:content='$t("view.favorite.visibility_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(type='default' icon='el-icon-view' size='mini' circle)
|
||||
el-dropdown-menu(#default='dropdown')
|
||||
el-dropdown-item(
|
||||
v-if='group.visibility !== visibility'
|
||||
v-for='visibility in worldGroupVisibilityOptions'
|
||||
:key='visibility'
|
||||
style='display: block; margin: 10px 0'
|
||||
v-text='visibility.charAt(0).toUpperCase() + visibility.slice(1)'
|
||||
@click.native='changeWorldGroupVisibility(group.name, visibility)')
|
||||
el-tooltip(
|
||||
placement='top'
|
||||
:content='$t("view.favorite.rename_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click.stop='changeFavoriteGroupName(group)'
|
||||
size='mini'
|
||||
icon='el-icon-edit'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='right'
|
||||
:content='$t("view.favorite.clear_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click.stop='clearFavoriteGroup(group)'
|
||||
size='mini'
|
||||
icon='el-icon-delete'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
.x-friend-list(v-if='group.count' style='margin-top: 10px')
|
||||
div(
|
||||
style='display: inline-block; width: 300px; margin-right: 15px'
|
||||
v-for='favorite in groupedByGroupKeyFavoriteWorlds[group.key]'
|
||||
:key='favorite.id'
|
||||
@click='showWorldDialog(favorite.id)')
|
||||
.x-friend-item
|
||||
template(v-if='favorite.ref')
|
||||
.avatar
|
||||
img(v-lazy='favorite.ref.thumbnailImageUrl')
|
||||
.detail
|
||||
span.name(v-text='favorite.ref.name')
|
||||
span.extra(v-if='favorite.ref.occupants') {{ favorite.ref.authorName }} ({{ favorite.ref.occupants }})
|
||||
span.extra(v-else v-text='favorite.ref.authorName')
|
||||
template(v-if='editFavoritesMode')
|
||||
el-dropdown(
|
||||
trigger='click'
|
||||
@click.native.stop
|
||||
size='mini'
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='left'
|
||||
:content='$t("view.favorite.move_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(type='default' icon='el-icon-back' size='mini' circle)
|
||||
el-dropdown-menu(#default='dropdown')
|
||||
template(
|
||||
v-if='groupAPI.name !== group.name'
|
||||
v-for='groupAPI in API.favoriteWorldGroups')
|
||||
el-dropdown-item(
|
||||
:key='groupAPI.name'
|
||||
style='display: block; margin: 10px 0'
|
||||
@click.native='moveFavorite(favorite.ref, groupAPI, "world")'
|
||||
:disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
|
||||
el-button(type='text' size='mini' @click.stop style='margin-left: 5px')
|
||||
el-checkbox(v-model='favorite.$selected')
|
||||
template(v-else)
|
||||
el-tooltip(
|
||||
v-if='favorite.deleted'
|
||||
placement='left'
|
||||
:content='$t("view.favorite.unavailable_tooltip")')
|
||||
i.el-icon-warning(style='color: #f56c6c; margin-left: 5px')
|
||||
el-tooltip(
|
||||
v-if='favorite.ref.releaseStatus === "private"'
|
||||
placement='left'
|
||||
:content='$t("view.favorite.private")')
|
||||
i.el-icon-warning(style='color: #e6a23c; margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='left'
|
||||
:content='$t("view.favorite.self_invite_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click.stop='newInstanceSelfInvite(favorite.id)'
|
||||
size='mini'
|
||||
icon='el-icon-message'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='right'
|
||||
:content='$t("view.favorite.unfavorite_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
v-if='shiftHeld'
|
||||
@click.stop='deleteFavorite(favorite.id)'
|
||||
size='mini'
|
||||
icon='el-icon-close'
|
||||
circle
|
||||
style='color: #f56c6c; margin-left: 5px')
|
||||
el-button(
|
||||
v-else
|
||||
@click.stop='showFavoriteDialog("world", favorite.id)'
|
||||
type='default'
|
||||
icon='el-icon-star-on'
|
||||
size='mini'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
template(v-else)
|
||||
.avatar
|
||||
.detail
|
||||
span(v-text='favorite.name || favorite.id')
|
||||
el-tooltip(
|
||||
v-if='favorite.deleted'
|
||||
placement='left'
|
||||
:content='$t("view.favorite.unavailable_tooltip")')
|
||||
i.el-icon-warning(style='color: #f56c6c; margin-left: 5px')
|
||||
el-button(
|
||||
type='text'
|
||||
icon='el-icon-close'
|
||||
size='mini'
|
||||
@click.stop='deleteFavorite(favorite.id)'
|
||||
style='margin-left: 5px')
|
||||
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(style='display: block; margin-top: 20px') {{ $t('view.favorite.worlds.local_favorites') }}
|
||||
br
|
||||
el-button(size='small' @click='promptNewLocalWorldFavoriteGroup') {{ $t('view.favorite.worlds.new_group') }}
|
||||
el-button(
|
||||
v-if='!refreshingLocalFavorites'
|
||||
size='small'
|
||||
@click='refreshLocalWorldFavorites'
|
||||
style='margin-left: 5px') {{ $t('view.favorite.worlds.refresh') }}
|
||||
el-button(v-else size='small' @click='refreshingLocalFavorites = false' style='margin-left: 5px')
|
||||
i.el-icon-loading(style='margin-right: 5px')
|
||||
span {{ $t('view.favorite.worlds.cancel_refresh') }}
|
||||
el-collapse-item(
|
||||
v-for='group in localWorldFavoriteGroups'
|
||||
v-if='localWorldFavorites[group]'
|
||||
:key='group')
|
||||
template(slot='title')
|
||||
span(v-text='group' style='font-weight: bold; font-size: 14px; margin-left: 10px')
|
||||
span(style='color: #909399; font-size: 12px; margin-left: 10px') {{ getLocalWorldFavoriteGroupLength(group) }}
|
||||
el-tooltip(
|
||||
placement='top'
|
||||
:content='$t("view.favorite.rename_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click.stop='promptLocalWorldFavoriteGroupRename(group)'
|
||||
size='mini'
|
||||
icon='el-icon-edit'
|
||||
circle
|
||||
style='margin-left: 10px')
|
||||
el-tooltip(
|
||||
placement='right'
|
||||
:content='$t("view.favorite.delete_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click.stop='promptLocalWorldFavoriteGroupDelete(group)'
|
||||
size='mini'
|
||||
icon='el-icon-delete'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
.x-friend-list(
|
||||
style='margin-top: 10px'
|
||||
v-if='localFavoriteShowDelayedContent[0] && localWorldFavorites[group].length')
|
||||
div(
|
||||
style='display: inline-block; width: 300px; margin-right: 15px'
|
||||
v-for='favorite in localWorldFavorites[group]'
|
||||
:key='favorite.id'
|
||||
@click='showWorldDialog(favorite.id)')
|
||||
.x-friend-item
|
||||
template(v-if='favorite.name')
|
||||
.avatar
|
||||
img(v-lazy='favorite.thumbnailImageUrl')
|
||||
.detail
|
||||
span.name(v-text='favorite.name')
|
||||
span.extra(v-if='favorite.occupants') {{ favorite.authorName }} ({{ favorite.occupants }})
|
||||
span.extra(v-else v-text='favorite.authorName')
|
||||
template(v-if='editFavoritesMode')
|
||||
el-dropdown(
|
||||
trigger='click'
|
||||
@click.native.stop
|
||||
size='mini'
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='left'
|
||||
:content='$t("view.favorite.copy_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(type='default' icon='el-icon-back' size='mini' circle)
|
||||
el-dropdown-menu(#default='dropdown')
|
||||
template(v-for='groupAPI in API.favoriteWorldGroups')
|
||||
el-dropdown-item(
|
||||
:key='groupAPI.name'
|
||||
style='display: block; margin: 10px 0'
|
||||
@click.native='addFavoriteWorld(favorite, groupAPI, true)'
|
||||
:disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
|
||||
template(v-else)
|
||||
el-tooltip(
|
||||
placement='left'
|
||||
:content='$t("view.favorite.self_invite_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
@click.stop='newInstanceSelfInvite(favorite.id)'
|
||||
size='mini'
|
||||
icon='el-icon-message'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
el-tooltip(
|
||||
placement='right'
|
||||
:content='$t("view.favorite.unfavorite_tooltip")'
|
||||
:disabled='hideTooltips')
|
||||
el-button(
|
||||
v-if='shiftHeld'
|
||||
@click.stop='removeLocalWorldFavorite(favorite.id, group)'
|
||||
size='mini'
|
||||
icon='el-icon-close'
|
||||
circle
|
||||
style='color: #f56c6c; margin-left: 5px')
|
||||
el-button(
|
||||
v-else
|
||||
@click.stop='showFavoriteDialog("world", favorite.id)'
|
||||
type='default'
|
||||
icon='el-icon-star-on'
|
||||
size='mini'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
template(v-else)
|
||||
.avatar
|
||||
.detail
|
||||
span(v-text='favorite.id')
|
||||
el-button(
|
||||
type='text'
|
||||
icon='el-icon-close'
|
||||
size='mini'
|
||||
@click.stop='removeLocalWorldFavorite(favorite.id, group)'
|
||||
style='margin-left: 5px')
|
||||
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
|
||||
favorites-world-tab(
|
||||
@show-world-export-dialog='showWorldExportDialog'
|
||||
@show-world-import-dialog='showWorldImportDialog'
|
||||
@save-sort-favorites-option='saveSortFavoritesOption'
|
||||
@show-world-dialog='showWorldDialog'
|
||||
@change-favorite-group-name='changeFavoriteGroupName'
|
||||
@clear-favorite-group='clearFavoriteGroup'
|
||||
@new-instance-self-invite='newInstanceSelfInvite'
|
||||
@show-favorite-dialog='showFavoriteDialog'
|
||||
@refresh-local-world-favorite='refreshLocalWorldFavorites'
|
||||
@delete-local-world-favorite-group='deleteLocalWorldFavoriteGroup'
|
||||
@search-world-favorites='searchWorldFavorites'
|
||||
@remove-local-world-favorite='removeLocalWorldFavorite'
|
||||
:sort-favorites.sync='sortFavorites'
|
||||
:world-favorite-search-results='worldFavoriteSearchResults'
|
||||
:hide-tooltips='hideTooltips'
|
||||
:favorite-worlds='favoriteWorlds'
|
||||
:edit-favorites-mode='editFavoritesMode'
|
||||
:shift-held='shiftHeld'
|
||||
:refresh-local-world-favorites='refreshLocalWorldFavorites'
|
||||
:local-world-favorite-groups='localWorldFavoriteGroups'
|
||||
:local-world-favorites='localWorldFavorites')
|
||||
el-tab-pane(:label='$t("view.favorite.avatars.header")' lazy)
|
||||
div(style='display: flex; align-items: center; justify-content: space-between')
|
||||
div
|
||||
@@ -681,9 +407,7 @@ mixin favoritesTab
|
||||
icon='el-icon-delete'
|
||||
circle
|
||||
style='margin-left: 5px')
|
||||
.x-friend-list(
|
||||
style='margin-top: 10px'
|
||||
v-if='localFavoriteShowDelayedContent[1] && localAvatarFavorites[group].length')
|
||||
.x-friend-list(style='margin-top: 10px' v-if='localAvatarFavorites[group].length')
|
||||
div(
|
||||
style='display: inline-block; width: 300px; margin-right: 15px'
|
||||
v-for='favorite in localAvatarFavorites[group]'
|
||||
|
||||
@@ -105,7 +105,7 @@ mixin notificationsTab
|
||||
@click='showFullscreenImageDialog(scope.row.imageUrl)')
|
||||
el-table-column(:label='$t("table.notification.message")' prop='message')
|
||||
template(#default='scope')
|
||||
span.x-link(v-if='scope.row.type === "invite"')
|
||||
span.x-link(v-if='scope.row.type === "invite"' style='display: flex')
|
||||
location(
|
||||
v-if='scope.row.details'
|
||||
:location='scope.row.details.worldId'
|
||||
|
||||
@@ -146,7 +146,3 @@
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* your component styles here */
|
||||
</style>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
import Location from '../../components/common/Location.vue';
|
||||
|
||||
export default {
|
||||
name: 'PreviousInstanceInfo',
|
||||
name: 'PreviousInstanceInfoDialog',
|
||||
components: {
|
||||
Location
|
||||
},
|
||||
931
src/views/dialogs/WorldDialog.vue
Normal file
931
src/views/dialogs/WorldDialog.vue
Normal file
@@ -0,0 +1,931 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
ref="worldDialog"
|
||||
class="x-dialog x-world-dialog"
|
||||
:visible.sync="worldDialog.visible"
|
||||
:show-close="false"
|
||||
width="770px">
|
||||
<div v-loading="worldDialog.loading">
|
||||
<div style="display: flex">
|
||||
<el-popover placement="right" width="500px" trigger="click">
|
||||
<img
|
||||
slot="reference"
|
||||
v-lazy="worldDialog.ref.thumbnailImageUrl"
|
||||
class="x-link"
|
||||
style="flex: none; width: 160px; height: 120px; border-radius: 12px" />
|
||||
<img
|
||||
v-lazy="worldDialog.ref.imageUrl"
|
||||
class="x-link"
|
||||
style="width: 500px; height: 375px"
|
||||
@click="showFullscreenImageDialog(worldDialog.ref.imageUrl)" />
|
||||
</el-popover>
|
||||
<div style="flex: 1; display: flex; align-items: center; margin-left: 15px">
|
||||
<div style="flex: 1">
|
||||
<div>
|
||||
<i
|
||||
v-show="
|
||||
API.currentUser.$homeLocation &&
|
||||
API.currentUser.$homeLocation.worldId === worldDialog.id
|
||||
"
|
||||
class="el-icon-s-home"
|
||||
style="margin-right: 5px" />
|
||||
<span class="dialog-title" v-text="worldDialog.ref.name" />
|
||||
</div>
|
||||
<div style="margin-top: 5px">
|
||||
<span
|
||||
class="x-link x-grey"
|
||||
style="font-family: monospace"
|
||||
@click="showUserDialog(worldDialog.ref.authorId)"
|
||||
v-text="worldDialog.ref.authorName" />
|
||||
</div>
|
||||
<div>
|
||||
<el-tag
|
||||
v-if="worldDialog.ref.$isLabs"
|
||||
type="primary"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.labs') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-else-if="worldDialog.ref.releaseStatus === 'public'"
|
||||
type="success"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.public') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-else
|
||||
type="danger"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.private') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.isPC"
|
||||
class="x-tag-platform-pc"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
PC
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="worldDialog.bundleSizes['standalonewindows']"
|
||||
class="x-grey"
|
||||
style="margin-left: 5px; border-left: inherit; padding-left: 5px">
|
||||
{{ worldDialog.bundleSizes['standalonewindows'].fileSize }}
|
||||
</span>
|
||||
<el-tag
|
||||
v-if="worldDialog.isQuest"
|
||||
class="x-tag-platform-quest"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
Android
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="worldDialog.bundleSizes['android']"
|
||||
class="x-grey"
|
||||
style="margin-left: 5px; border-left: inherit; padding-left: 5px">
|
||||
{{ worldDialog.bundleSizes['android'].fileSize }}
|
||||
</span>
|
||||
<el-tag
|
||||
v-if="worldDialog.isIos"
|
||||
class="x-tag-platform-ios"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
iOS
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="worldDialog.bundleSizes['ios']"
|
||||
class="x-grey"
|
||||
style="margin-left: 5px; border-left: inherit; padding-left: 5px">
|
||||
{{ worldDialog.bundleSizes['ios'].fileSize }}
|
||||
</span>
|
||||
<el-tag
|
||||
v-if="worldDialog.avatarScalingDisabled"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.avatar_scaling_disabled') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.focusViewDisabled"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.focus_view_disabled') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.stickersDisabled"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.stickers_disabled') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.ref.unityPackageUrl"
|
||||
type="success"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.future_proofing') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.inCache"
|
||||
class="x-link"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px"
|
||||
@click="openFolderGeneric(worldDialog.cachePath)">
|
||||
<span v-text="worldDialog.cacheSize" />
|
||||
| {{ $t('dialog.world.tags.cache') }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div>
|
||||
<template v-for="tag in worldDialog.ref.tags">
|
||||
<el-tag
|
||||
v-if="tag.startsWith('content_')"
|
||||
:key="tag"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
<template v-if="tag === 'content_horror'">
|
||||
{{ $t('dialog.world.tags.content_horror') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_gore'">
|
||||
{{ $t('dialog.world.tags.content_gore') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_violence'">
|
||||
{{ $t('dialog.world.tags.content_violence') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_adult'">
|
||||
{{ $t('dialog.world.tags.content_adult') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_sex'">
|
||||
{{ $t('dialog.world.tags.content_sex') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ tag.replace('content_', '') }}
|
||||
</template>
|
||||
</el-tag>
|
||||
</template>
|
||||
</div>
|
||||
<div style="margin-top: 5px">
|
||||
<span
|
||||
v-show="worldDialog.ref.name !== worldDialog.ref.description"
|
||||
style="font-size: 12px"
|
||||
>{{ worldDialog.ref.description }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: none; margin-left: 10px">
|
||||
<el-tooltip
|
||||
v-if="worldDialog.inCache"
|
||||
placement="top"
|
||||
:content="$t('dialog.world.actions.delete_cache_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
icon="el-icon-delete"
|
||||
circle
|
||||
:disabled="isGameRunning && worldDialog.cacheLocked"
|
||||
@click="deleteVRChatCache(worldDialog.ref)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="worldDialog.isFavorite"
|
||||
placement="top"
|
||||
:content="$t('dialog.world.actions.favorites_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
type="default"
|
||||
:icon="worldDialog.isFavorite ? 'el-icon-star-on' : 'el-icon-star-off'"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
@click="worldDialogCommand('Add Favorite')" />
|
||||
</el-tooltip>
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
size="small"
|
||||
style="margin-left: 5px"
|
||||
@command="worldDialogCommand">
|
||||
<el-button type="default" icon="el-icon-more" circle />
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item icon="el-icon-refresh" command="Refresh">
|
||||
{{ $t('dialog.world.actions.refresh') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-share" command="Share">
|
||||
{{ $t('dialog.world.actions.share') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-s-flag" command="New Instance" divided>
|
||||
{{ $t('dialog.world.actions.new_instance') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-message" command="New Instance and Self Invite">
|
||||
{{ $t('dialog.world.actions.new_instance_and_self_invite') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="
|
||||
API.currentUser.$homeLocation &&
|
||||
API.currentUser.$homeLocation.worldId === worldDialog.id
|
||||
"
|
||||
icon="el-icon-magic-stick"
|
||||
command="Reset Home"
|
||||
divided>
|
||||
{{ $t('dialog.world.actions.reset_home') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-else icon="el-icon-s-home" command="Make Home" divided>
|
||||
{{ $t('dialog.world.actions.make_home') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-tickets" command="Previous Instances">
|
||||
{{ $t('dialog.world.actions.show_previous_instances') }}
|
||||
</el-dropdown-item>
|
||||
<template v-if="API.currentUser.id !== worldDialog.ref.authorId">
|
||||
<el-dropdown-item icon="el-icon-picture-outline" command="Previous Images">
|
||||
{{ $t('dialog.world.actions.show_previous_images') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:disabled="!worldDialog.hasPersistData"
|
||||
icon="el-icon-upload"
|
||||
command="Delete Persistent Data">
|
||||
{{ $t('dialog.world.actions.delete_persistent_data') }}
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Rename">
|
||||
{{ $t('dialog.world.actions.rename') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Description">
|
||||
{{ $t('dialog.world.actions.change_description') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Capacity">
|
||||
{{ $t('dialog.world.actions.change_capacity') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Recommended Capacity">
|
||||
{{ $t('dialog.world.actions.change_recommended_capacity') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change YouTube Preview">
|
||||
{{ $t('dialog.world.actions.change_preview') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Tags">
|
||||
{{ $t('dialog.world.actions.change_tags') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Allowed Domains">
|
||||
{{ $t('dialog.world.actions.change_allowed_video_player_domains') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-picture-outline" command="Change Image">
|
||||
{{ $t('dialog.world.actions.change_image') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="worldDialog.ref.unityPackageUrl"
|
||||
icon="el-icon-download"
|
||||
command="Download Unity Package">
|
||||
{{ $t('dialog.world.actions.download_package') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="
|
||||
worldDialog.ref?.tags?.includes('system_approved') ||
|
||||
worldDialog.ref?.tags?.includes('system_labs')
|
||||
"
|
||||
icon="el-icon-view"
|
||||
command="Unpublish"
|
||||
divided>
|
||||
{{ $t('dialog.world.actions.unpublish') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-else icon="el-icon-view" command="Publish" divided>
|
||||
{{ $t('dialog.world.actions.publish_to_labs') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:disabled="!worldDialog.hasPersistData"
|
||||
icon="el-icon-upload"
|
||||
command="Delete Persistent Data">
|
||||
{{ $t('dialog.world.actions.delete_persistent_data') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-delete" command="Delete" style="color: #f56c6c">
|
||||
{{ $t('dialog.world.actions.delete') }}
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-tabs>
|
||||
<el-tab-pane :label="$t('dialog.world.instances.header')">
|
||||
<div class="">
|
||||
<i class="el-icon-user" />
|
||||
{{ $t('dialog.world.instances.public_count', { count: worldDialog.ref.publicOccupants }) }}
|
||||
<i class="el-icon-user-solid" style="margin-left: 10px" />
|
||||
{{ $t('dialog.world.instances.private_count', { count: worldDialog.ref.privateOccupants }) }}
|
||||
<i class="el-icon-check" style="margin-left: 10px" />
|
||||
{{
|
||||
$t('dialog.world.instances.capacity_count', {
|
||||
count: worldDialog.ref.recommendedCapacity,
|
||||
max: worldDialog.ref.capacity
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
<div v-for="room in worldDialog.rooms" :key="room.id">
|
||||
<div style="margin: 5px 0">
|
||||
<location-world
|
||||
:locationobject="room.$location"
|
||||
:currentuserid="API.currentUser.id"
|
||||
:worlddialogshortname="worldDialog.$location.shortName"
|
||||
@show-launch-dialog="showLaunchDialog" />
|
||||
<launch
|
||||
:location="room.tag"
|
||||
style="margin-left: 5px"
|
||||
@show-launch-dialog="showLaunchDialog" />
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('dialog.world.instances.self_invite_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<invite-yourself
|
||||
:location="room.$location.tag"
|
||||
:shortname="room.$location.shortName"
|
||||
style="margin-left: 5px" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('dialog.world.instances.refresh_instance_info')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-refresh"
|
||||
style="margin-left: 5px"
|
||||
circle
|
||||
@click="refreshInstancePlayerCount(room.tag)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="instanceJoinHistory.get(room.$location.tag)"
|
||||
placement="top"
|
||||
:content="$t('dialog.previous_instances.info')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-s-data"
|
||||
style="margin-left: 5px"
|
||||
plain
|
||||
circle
|
||||
@click="showPreviousInstanceInfoDialog(room.location)" />
|
||||
</el-tooltip>
|
||||
<last-join :location="room.$location.tag" :currentlocation="lastLocation.location" />
|
||||
<instance-info
|
||||
:location="room.tag"
|
||||
:instance="room.ref"
|
||||
:friendcount="room.friendCount"
|
||||
:updateelement="updateInstanceInfo" />
|
||||
<div
|
||||
v-if="room.$location.userId || room.users.length"
|
||||
class="x-friend-list"
|
||||
style="margin: 10px 0; max-height: unset">
|
||||
<div
|
||||
v-if="room.$location.userId"
|
||||
class="x-friend-item x-friend-item-border"
|
||||
@click="showUserDialog(room.$location.userId)">
|
||||
<template v-if="room.$location.user">
|
||||
<div class="avatar" :class="userStatusClass(room.$location.user)">
|
||||
<img v-lazy="userImage(room.$location.user)" />
|
||||
</div>
|
||||
<div class="detail">
|
||||
<span
|
||||
class="name"
|
||||
:style="{ color: room.$location.user.$userColour }"
|
||||
v-text="room.$location.user.displayName" />
|
||||
<span class="extra">
|
||||
{{ $t('dialog.world.instances.instance_creator') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else v-text="room.$location.userId" />
|
||||
</div>
|
||||
<div
|
||||
v-for="user in room.users"
|
||||
:key="user.id"
|
||||
class="x-friend-item x-friend-item-border"
|
||||
@click="showUserDialog(user.id)">
|
||||
<div class="avatar" :class="userStatusClass(user)">
|
||||
<img v-lazy="userImage(user)" />
|
||||
</div>
|
||||
<div class="detail">
|
||||
<span
|
||||
class="name"
|
||||
:style="{ color: user.$userColour }"
|
||||
v-text="user.displayName" />
|
||||
<span v-if="user.location === 'traveling'" class="extra">
|
||||
<i class="el-icon-loading" style="margin-right: 5px" />
|
||||
<timer :epoch="user.$travelingToTime" />
|
||||
</span>
|
||||
<span v-else class="extra">
|
||||
<timer :epoch="user.$location_at" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('dialog.world.info.header')" lazy>
|
||||
<div class="x-friend-list" style="max-height: none">
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.memo') }}
|
||||
</span>
|
||||
<el-input
|
||||
v-model="worldDialog.memo"
|
||||
class="extra"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
:autosize="{ minRows: 1, maxRows: 20 }"
|
||||
:placeholder="$t('dialog.world.info.memo_placeholder')"
|
||||
size="mini"
|
||||
resize="none"
|
||||
@change="onWorldMemoChange" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100%; display: flex">
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.id') }}
|
||||
</span>
|
||||
<span class="extra" style="display: inline">
|
||||
{{ worldDialog.id }}
|
||||
</span>
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('dialog.world.info.id_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
size="mini"
|
||||
style="margin-left: 5px"
|
||||
@click.native.stop>
|
||||
<el-button type="default" icon="el-icon-s-order" size="mini" circle />
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="copyWorldId(worldDialog.id)">
|
||||
{{ $t('dialog.world.info.copy_id') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="copyWorldUrl(worldDialog.id)">
|
||||
{{ $t('dialog.world.info.copy_url') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="copyWorldName(worldDialog.ref.name)">
|
||||
{{ $t('dialog.world.info.copy_name') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="worldDialog.ref.previewYoutubeId"
|
||||
class="x-friend-item"
|
||||
style="width: 350px"
|
||||
@click="
|
||||
openExternalLink(`https://www.youtube.com/watch?v=${worldDialog.ref.previewYoutubeId}`)
|
||||
">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.youtube_preview') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
https://www.youtube.com/watch?v={{ worldDialog.ref.previewYoutubeId }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.author_tags') }}
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
worldDialog.ref.tags?.filter((tag) => tag.startsWith('author_tag')).length > 0
|
||||
"
|
||||
class="extra">
|
||||
{{ worldTags }}
|
||||
</span>
|
||||
<span v-else class="extra"> - </span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.players') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.occupants | commaNumber }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.favorites') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.favorites | commaNumber
|
||||
}}<span
|
||||
v-if="worldDialog.ref?.favorites > 0 && worldDialog.ref?.visits > 0"
|
||||
class="extra">
|
||||
({{ favoriteRate }}%)
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.visits') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.visits | commaNumber }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.capacity') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.recommendedCapacity | commaNumber }} ({{
|
||||
worldDialog.ref.capacity | commaNumber
|
||||
}})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.created_at') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.created_at | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.last_updated') }}
|
||||
</span>
|
||||
<span v-if="worldDialog.lastUpdated" class="extra">
|
||||
{{ worldDialog.lastUpdated | formatDate('long') }}
|
||||
</span>
|
||||
<span v-else class="extra">
|
||||
{{ worldDialog.ref.updated_at | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="worldDialog.ref.labsPublicationDate !== 'none'"
|
||||
class="x-friend-item"
|
||||
style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.labs_publication_date') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.labsPublicationDate | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="worldDialog.ref.publicationDate !== 'none'"
|
||||
class="x-friend-item"
|
||||
style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name" style="display: inline">
|
||||
{{ $t('dialog.world.info.publication_date') }}
|
||||
</span>
|
||||
<el-tooltip v-if="isTimeInLabVisible" placement="top" style="margin-left: 5px">
|
||||
<template slot="content">
|
||||
<span>
|
||||
{{ $t('dialog.world.info.time_in_labs') }}
|
||||
{{ timeInLab }}
|
||||
</span>
|
||||
</template>
|
||||
<i class="el-icon-arrow-down" />
|
||||
</el-tooltip>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.publicationDate | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.version') }}
|
||||
</span>
|
||||
<span class="extra" v-text="worldDialog.ref.version" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.heat') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.heat | commaNumber }} {{ '🔥'.repeat(worldDialog.ref.heat) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.popularity') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.popularity | commaNumber }}
|
||||
{{ '💖'.repeat(worldDialog.ref.popularity) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.platform') }}
|
||||
</span>
|
||||
<span class="extra" style="white-space: normal">{{ worldDialogPlatform }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.last_visited') }}
|
||||
<el-tooltip
|
||||
v-if="!hideTooltips"
|
||||
placement="top"
|
||||
style="margin-left: 5px"
|
||||
:content="$t('dialog.world.info.accuracy_notice')"
|
||||
><i class="el-icon-warning"></i
|
||||
></el-tooltip>
|
||||
</span>
|
||||
<span class="extra">{{ worldDialog.lastVisit | formatDate('long') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-tooltip
|
||||
:disabled="hideTooltips"
|
||||
placement="top"
|
||||
:content="$t('dialog.user.info.open_previouse_instance')">
|
||||
<div class="x-friend-item" @click="showPreviousInstancesWorldDialog(worldDialog.ref)">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.visit_count') }}
|
||||
<el-tooltip
|
||||
v-if="!hideTooltips"
|
||||
placement="top"
|
||||
style="margin-left: 5px"
|
||||
:content="$t('dialog.world.info.accuracy_notice')"
|
||||
><i class="el-icon-warning"></i
|
||||
></el-tooltip>
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.visitCount }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name"
|
||||
>{{ $t('dialog.world.info.time_spent') }}
|
||||
<el-tooltip
|
||||
v-if="!hideTooltips"
|
||||
placement="top"
|
||||
style="margin-left: 5px"
|
||||
:content="$t('dialog.world.info.accuracy_notice')">
|
||||
<i class="el-icon-warning"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.timeSpent === 0 ? ' - ' : timeSpent }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('dialog.world.json.header')" style="max-height: 50vh" lazy>
|
||||
<el-button
|
||||
type="default"
|
||||
size="mini"
|
||||
icon="el-icon-refresh"
|
||||
circle
|
||||
@click="refreshWorldDialogTreeData()"></el-button>
|
||||
<el-button
|
||||
type="default"
|
||||
size="mini"
|
||||
icon="el-icon-download"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
@click="downloadAndSaveJson(worldDialog.id, worldDialog.ref)"></el-button>
|
||||
<el-tree :data="treeData" style="margin-top: 5px; font-size: 12px">
|
||||
<template slot-scope="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>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import utils from '../../classes/utils';
|
||||
import database from '../../repository/database.js';
|
||||
export default {
|
||||
name: 'WorldDialog',
|
||||
inject: ['API', 'showUserDialog', 'userStatusClass', 'userImage', 'adjustDialogZ'],
|
||||
props: {
|
||||
worldDialog: Object,
|
||||
hideTooltips: Boolean,
|
||||
isGameRunning: Boolean,
|
||||
lastLocation: Object,
|
||||
instanceJoinHistory: Map,
|
||||
|
||||
// ok
|
||||
updateInstanceInfo: Number
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
treeData: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isTimeInLabVisible() {
|
||||
return (
|
||||
this.worldDialog.ref.publicationDate &&
|
||||
this.worldDialog.ref.publicationDate !== 'none' &&
|
||||
this.worldDialog.ref.labsPublicationDate &&
|
||||
this.worldDialog.ref.labsPublicationDate !== 'none'
|
||||
);
|
||||
},
|
||||
|
||||
timeInLab() {
|
||||
return utils.timeToText(
|
||||
new Date(this.worldDialog.ref?.publicationDate) -
|
||||
new Date(this.worldDialog.ref?.labsPublicationDate)
|
||||
);
|
||||
},
|
||||
favoriteRate() {
|
||||
return (
|
||||
Math.round(
|
||||
(((this.worldDialog.ref?.favorites - this.worldDialog.ref?.visits) /
|
||||
this.worldDialog.ref?.visits) *
|
||||
100 +
|
||||
100) *
|
||||
100
|
||||
) / 100
|
||||
);
|
||||
},
|
||||
worldTags() {
|
||||
return this.worldDialog.ref?.tags
|
||||
.filter((tag) => tag.startsWith('author_tag'))
|
||||
.map((tag) => tag.replace('author_tag_', ''))
|
||||
.join(', ');
|
||||
},
|
||||
timeSpent() {
|
||||
return utils.timeToText(this.worldDialog.timeSpent);
|
||||
},
|
||||
worldDialogPlatform() {
|
||||
const { ref } = this.worldDialog;
|
||||
const platforms = [];
|
||||
if (ref.unityPackages) {
|
||||
for (const unityPackage of ref.unityPackages) {
|
||||
let platform = 'PC';
|
||||
if (unityPackage.platform === 'standalonewindows') {
|
||||
platform = 'PC';
|
||||
} else if (unityPackage.platform === 'android') {
|
||||
platform = 'Android';
|
||||
} else if (unityPackage.platform) {
|
||||
({ platform } = unityPackage);
|
||||
}
|
||||
platforms.unshift(`${platform}/${unityPackage.unityVersion}`);
|
||||
}
|
||||
}
|
||||
return platforms.join(', ');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'worldDialog.visible'(value) {
|
||||
if (value) {
|
||||
this.$nextTick(() => this.adjustDialogZ(this.$refs.worldDialog.$el));
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showFullscreenImageDialog(imageUrl) {
|
||||
this.$emit('show-fullscreen-image-dialog', imageUrl);
|
||||
},
|
||||
openFolderGeneric(path) {
|
||||
this.$emit('open-folder-generic', path);
|
||||
},
|
||||
deleteVRChatCache(world) {
|
||||
this.$emit('delete-vrchat-cache', world);
|
||||
},
|
||||
worldDialogCommand(command) {
|
||||
if (command === 'Share') {
|
||||
this.copyWorldUrl();
|
||||
} else {
|
||||
this.$emit('world-dialog-command', command);
|
||||
}
|
||||
},
|
||||
showLaunchDialog(location, shortName) {
|
||||
this.$emit('show-launch-dialog', location, shortName);
|
||||
},
|
||||
refreshInstancePlayerCount(tag) {
|
||||
this.$emit('refresh-instance-player-count', tag);
|
||||
},
|
||||
showPreviousInstanceInfoDialog(location) {
|
||||
this.$emit('show-previous-instance-info-dialog', location);
|
||||
},
|
||||
onWorldMemoChange() {
|
||||
const worldId = this.worldDialog.id;
|
||||
const memo = this.worldDialog.memo;
|
||||
if (memo) {
|
||||
database.setWorldMemo({
|
||||
worldId,
|
||||
editedAt: new Date().toJSON(),
|
||||
memo
|
||||
});
|
||||
} else {
|
||||
database.deleteWorldMemo(id);
|
||||
}
|
||||
},
|
||||
showPreviousInstancesWorldDialog(world) {
|
||||
this.$emit('show-previous-instances-world-dialog', world);
|
||||
},
|
||||
refreshWorldDialogTreeData() {
|
||||
this.treeData = utils.buildTreeData(this.worldDialog.ref);
|
||||
},
|
||||
downloadAndSaveJson(id, ref) {
|
||||
this.$emit('download-and-save-json', id, ref);
|
||||
},
|
||||
copyWorldId() {
|
||||
navigator.clipboard
|
||||
.writeText(this.worldDialog.id)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'World ID copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('copy failed:', err);
|
||||
this.$message({
|
||||
message: 'Copy failed',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
copyWorldUrl() {
|
||||
navigator.clipboard
|
||||
.writeText(`https://vrchat.com/home/world/${this.worldDialog.id}`)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'World URL copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('copy failed:', err);
|
||||
this.$message({
|
||||
message: 'Copy failed',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
copyWorldName() {
|
||||
navigator.clipboard
|
||||
.writeText(this.worldDialog.ref.name)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'World name copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('copy failed:', err);
|
||||
this.$message({
|
||||
message: 'Copy failed',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user