diff --git a/html/src/app.js b/html/src/app.js index 7b205090..2de7732c 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -208,23 +208,6 @@ speechSynthesis.getVoices(); $appDarkStyle.href = `app.dark.css?_=${Date.now()}`; document.head.appendChild($appDarkStyle); - var getLaunchURL = function (instance) { - var L = instance; - if (L.instanceId) { - if (L.shortName.length > 0 && L.userId != null) { - return `https://vrchat.com/home/launch?worldId=${ - encodeURIComponent(L.worldId) - }&instanceId=${encodeURIComponent(L.instanceId)}&shortName=${encodeURIComponent(L.shortName)}`; - } - return `https://vrchat.com/home/launch?worldId=${encodeURIComponent( - L.worldId - )}&instanceId=${encodeURIComponent(L.instanceId)}`; - } - return `https://vrchat.com/home/launch?worldId=${encodeURIComponent( - L.worldId - )}`; - }; - // // Languages // @@ -692,10 +675,12 @@ speechSynthesis.getVoices(); } else if (_tag.startsWith('local') === false) { var sep = _tag.indexOf(':'); // technically not part of instance id, but might be there when coping id from url so why not support it - var shortNameQualifier = "&shortName=" - var shortNameIndex = _tag.indexOf(shortNameQualifier) + var shortNameQualifier = '&shortName='; + var shortNameIndex = _tag.indexOf(shortNameQualifier); if (shortNameIndex >= 0) { - ctx.shortName = _tag.substr(shortNameIndex + shortNameQualifier.length) + ctx.shortName = _tag.substr( + shortNameIndex + shortNameQualifier.length + ); _tag = _tag.substr(0, shortNameIndex); } if (sep >= 0) { @@ -1992,9 +1977,6 @@ speechSynthesis.getVoices(); json, params }; - if (args.json) { - args.shortOrSecureName = args.json.shortName ?? args.json.secureName; - } this.$emit('INSTANCE:SHORTNAME', args); return args; }); @@ -2007,6 +1989,9 @@ speechSynthesis.getVoices(); } */ API.selfInvite = function (params) { + if (params.shortName === '') { + delete params.shortName; + } return this.call( `invite/myself/to/${params.worldId}:${params.instanceId}`, { @@ -10164,7 +10149,7 @@ speechSynthesis.getVoices(); } switch (L.accessType) { case 'public': - L.joinUrl = getLaunchURL(L); + L.joinUrl = this.getLaunchURL(L); L.accessName = `Public #${L.instanceName} (${platform})`; break; case 'invite+': @@ -12543,16 +12528,20 @@ speechSynthesis.getVoices(); } }); }; - - $app.methods.directAccessWorld = function (input) { - if (input.startsWith("/home/")) { - input = "https://vrchat.com" + input; + + $app.methods.directAccessWorld = function (textBoxInput) { + var input = textBoxInput; + if (input.startsWith('/home/')) { + input = `https://vrchat.com${input}`; } if (input.startsWith('https://vrch.at')) { return AppApi.FollowUrl(input).then((output) => { return this.directAccessWorld(output); }); - } else if (input.startsWith('https://vrchat.') || input.startsWith("/home/")) { + } else if ( + input.startsWith('https://vrchat.') || + input.startsWith('/home/') + ) { var url = new URL(input); var urlPath = url.pathname; if (urlPath.substring(5, 12) === '/world/') { @@ -12575,8 +12564,8 @@ speechSynthesis.getVoices(); } } else if (input.substring(0, 5) === 'wrld_') { // a bit hacky, but supports weird malformed inputs cut out from url, why not - if (input.indexOf("&instanceId=") >= 0) { - input = "https://vrchat.com/home/launch?worldId=" + input; + if (input.indexOf('&instanceId=') >= 0) { + input = `https://vrchat.com/home/launch?worldId=${input}`; return this.directAccessWorld(input); } this.showWorldDialog(input.trim()); @@ -14346,16 +14335,14 @@ speechSynthesis.getVoices(); D.isFavorite = false; }); - $app.methods.showWorldDialog = function (tag, shortName = void 0) { + $app.methods.showWorldDialog = function (tag, shortName) { this.$nextTick(() => adjustDialogZ(this.$refs.worldDialog.$el)); var D = this.worldDialog; var L = API.parseLocation(tag); if (L.worldId === '') { return; } - if (!L.shortName && shortName) { - L.shortName = shortName; - } + L.shortName = shortName; if (L.worldId === L.instanceId) { // very janky fix for removing empty worldId instance L.instanceId = ''; @@ -14458,7 +14445,7 @@ speechSynthesis.getVoices(); id: instanceId, occupants: 0, friendCount: 0, - shortName: shortName, + shortName, users: [] }; } @@ -15161,8 +15148,7 @@ speechSynthesis.getVoices(); var L = API.parseLocation(D.worldId); API.selfInvite({ instanceId: L.instanceId, - worldId: L.worldId, - shortName: L.shortName + worldId: L.worldId }).finally(inviteLoop); } else { API.sendInvite( @@ -15435,7 +15421,7 @@ speechSynthesis.getVoices(); this.updateNewInstanceDialog(false); }; - $app.methods.selfInvite = function (location, shortName = void 0) { + $app.methods.selfInvite = function (location, shortName) { var L = API.parseLocation(location); if (L.isOffline || L.isTraveling || L.worldId === '') { return; @@ -15451,7 +15437,7 @@ speechSynthesis.getVoices(); API.selfInvite({ instanceId: L.instanceId, worldId: L.worldId, - shortName: shortName ?? L.shortName + shortName }).then((args) => { this.$message({ message: 'Self invite sent', @@ -15461,7 +15447,7 @@ speechSynthesis.getVoices(); }); }; - $app.methods.updateNewInstanceDialog = function (noChanges = false) { + $app.methods.updateNewInstanceDialog = function (noChanges) { var D = $app.newInstanceDialog; if (D.instanceId) { D.location = `${D.worldId}:${D.instanceId}`; @@ -15474,7 +15460,7 @@ speechSynthesis.getVoices(); } else { D.shortName = ''; } - D.url = getLaunchURL(L); + D.url = this.getLaunchURL(L); }; var saveNewInstanceDialog = function () { @@ -15504,7 +15490,8 @@ speechSynthesis.getVoices(); ); $app.buildInstance(); }; - $app.watch['newInstanceDialog.worldId'] = $app.methods.updateNewInstanceDialog; + $app.watch['newInstanceDialog.worldId'] = + $app.methods.updateNewInstanceDialog; $app.watch['newInstanceDialog.instanceName'] = saveNewInstanceDialog; $app.watch['newInstanceDialog.accessType'] = saveNewInstanceDialog; $app.watch['newInstanceDialog.region'] = saveNewInstanceDialog; @@ -15703,6 +15690,7 @@ speechSynthesis.getVoices(); visible: false, loading: false, desktop: configRepository.getBool('launchAsDesktop'), + tag: '', location: '', url: '', shortName: '', @@ -15718,53 +15706,84 @@ speechSynthesis.getVoices(); }); API.$on('INSTANCE:SHORTNAME', function (args) { - var url = ''; - var shortName = ''; - if (args.json && args.shortOrSecureName) { - shortName = args.shortOrSecureName; - url = `https://vrch.at/${shortName}`; + if (!args.params || !args.json || !args.json.shortName) { + return; + } + var shortName = args.json.shortName; + var location = `${args.params.worldId}:${args.params.instanceId}`; + if (location === $app.launchDialog.tag) { + var L = this.parseLocation(location); + L.shortName = shortName; + $app.launchDialog.shortName = shortName; + $app.launchDialog.shortUrl = `https://vrch.at/${shortName}`; + $app.launchDialog.url = $app.getLaunchURL(L); + } + if (location === $app.newInstanceDialog.location) { + $app.newInstanceDialog.shortName = shortName; + $app.updateNewInstanceDialog(true); } - $app.newInstanceDialog.shortName = shortName; - $app.launchDialog.shortName = shortName; - $app.launchDialog.shortUrl = url; - $app.launchDialog.url = $app.addShortNameToFullUrl($app.launchDialog.url, shortName); - $app.updateNewInstanceDialog(true); }); - $app.methods.addShortNameToFullUrl = function(input, shortName) { - if (input.trim().length == 0) { + $app.methods.addShortNameToFullUrl = function (input, shortName) { + if (input.trim().length === 0 || !shortName) { return input; } var url = new URL(input); var urlParams = new URLSearchParams(url.search); - urlParams.set("shortName", shortName); + urlParams.set('shortName', shortName); url.search = urlParams.toString(); return url.toString(); - } + }; - $app.methods.showLaunchDialog = function (tag) { + $app.methods.showLaunchDialog = function (tag, shortName) { this.$nextTick(() => adjustDialogZ(this.$refs.launchDialog.$el)); + var D = this.launchDialog; + D.tag = tag; + D.shortUrl = ''; + D.shortName = ''; var L = API.parseLocation(tag); + L.shortName = shortName; if (L.isOffline || L.isPrivate || L.isTraveling || L.worldId === '') { return; } - var D = this.launchDialog; + if (shortName) { + D.shortName = shortName; + D.shortUrl = `https://vrch.at/${shortName}`; + } if (L.instanceId) { D.location = `${L.worldId}:${L.instanceId}`; } else { D.location = L.worldId; } - D.shortUrl = ''; - D.url = getLaunchURL(L); + D.url = this.getLaunchURL(L); D.visible = true; - if (L.userId != null) { + if (L.userId && !shortName) { API.getInstanceShortName({ worldId: L.worldId, instanceId: L.instanceId - }) + }); } }; + $app.methods.getLaunchURL = function (instance) { + var L = instance; + if (L.instanceId) { + if (L.shortName) { + return `https://vrchat.com/home/launch?worldId=${encodeURIComponent( + L.worldId + )}&instanceId=${encodeURIComponent( + L.instanceId + )}&shortName=${encodeURIComponent(L.shortName)}`; + } + return `https://vrchat.com/home/launch?worldId=${encodeURIComponent( + L.worldId + )}&instanceId=${encodeURIComponent(L.instanceId)}`; + } + return `https://vrchat.com/home/launch?worldId=${encodeURIComponent( + L.worldId + )}`; + }; + $app.methods.locationToLaunchArg = function (location) { return `vrchat://launch?id=${location}`; }; @@ -15801,40 +15820,27 @@ speechSynthesis.getVoices(); document.execCommand('copy'); document.getElementById('copy_to_clipboard').remove(); }; - - $app.methods.copyInstanceUrlAndUpdateNewInstanceDialog = function (url) { - this.copyInstanceUrl(url) - .then(url => { - $app.newInstanceDialog.url = url; - $app.updateNewInstanceDialog(true) - }); - } - $app.methods.copyInstanceUrl = function (url) { - var copyUrl = function (url) { - $app.copyToClipboard(url); - $app.$message({ - message: 'Instance URL copied to clipboard', - type: 'success' - }); - return url; + $app.methods.copyInstanceMessage = function (input) { + this.copyToClipboard(input); + this.$message({ + message: 'Instance copied to clipboard', + type: 'success' + }); + return input; + }; + + $app.methods.copyInstanceUrl = async function (location) { + var L = API.parseLocation(location); + var args = await API.getInstanceShortName({ + worldId: L.worldId, + instanceId: L.instanceId + }); + if (args.json && args.json.shortName) { + L.shortName = args.json.shortName; } - var location = this.parseLocationUrl(url) - if (!location.shortName) { - return API.getInstanceShortName({ - worldId: location.worldId, - instanceId: location.instanceId - }).then((args) => { - if (args.json && args.shortOrSecureName) { - var newUrl = this.addShortNameToFullUrl(url, args.shortOrSecureName) - return copyUrl(newUrl); - } else { - return copyUrl(url); - } - }); - } - copyUrl(url); - return Promise.resolve(url); + var newUrl = this.getLaunchURL(L); + this.copyInstanceMessage(newUrl); }; $app.methods.copyAvatarId = function (avatarId) { @@ -16534,8 +16540,7 @@ speechSynthesis.getVoices(); var L = API.parseLocation(J.worldId); API.selfInvite({ instanceId: L.instanceId, - worldId: L.worldId, - shortName: L.shortName + worldId: L.worldId }).finally(inviteLoop); } else if ($app.uploadImage) { API.sendInvitePhoto( @@ -16562,7 +16567,7 @@ speechSynthesis.getVoices(); J.loading = false; J.visible = false; this.$message({ - message: 'Invite message sent', + message: 'Invite sent', type: 'success' }); } @@ -16705,8 +16710,7 @@ speechSynthesis.getVoices(); var L = API.parseLocation(J.worldId); API.selfInvite({ instanceId: L.instanceId, - worldId: L.worldId, - shortName: L.shortName + worldId: L.worldId }).finally(inviteLoop); } else if ($app.uploadImage) { API.sendInvitePhoto( @@ -18551,36 +18555,6 @@ speechSynthesis.getVoices(); $app.downloadDialog.visible = false; }); - // Parse location URL - - $app.methods.parseLocationUrl = function (location) { - var url = new URL(location); - var urlPath = url.pathname; - if (urlPath.substring(5, 12) === '/world/') { - var worldId = urlPath.substring(12); - return worldId; - } - if (urlPath.substring(5, 12) === '/launch') { - var urlParams = new URLSearchParams(url.search); - var worldId = urlParams.get('worldId'); - var instanceId = urlParams.get('instanceId'); - var shortName = urlParams.get('shortName'); - var location; - if (instanceId) { - location = `${worldId}:${instanceId}`; - } else if (worldId) { - location = worldId; - } - return { - worldId: worldId, - instanceId: instanceId, - location: location, - shortName: shortName - } - } - return void 0; - }; - // Parse User URL $app.methods.parseUserUrl = function (user) { diff --git a/html/src/index.pug b/html/src/index.pug index fa2ce749..5c57fd6c 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -1543,7 +1543,7 @@ html el-tooltip(placement="top" content="Launch/Invite" :disabled="hideTooltips") launch(:location="userDialog.$location.tag" style="margin-left:5px") el-tooltip(placement="top" content="Invite yourself" :disabled="hideTooltips") - invite-yourself(:locaTion="userDialog.$location.tag" :shortname="userDialog.$location.shortName" style="margin-left:5px") + invite-yourself(:location="userDialog.$location.tag" :shortname="userDialog.$location.shortName" style="margin-left:5px") el-tooltip(placement="top" content="Refresh player count" :disabled="hideTooltips") el-button(v-if="userDialog.$location.tag !== lastLocation.location" @click="refreshInstancePlayerCount(userDialog.$location.tag)" size="mini" icon="el-icon-refresh" style="margin-left:5px" circle) span(v-if="userDialog.instance.occupants" style="margin-left:5px") {{ userDialog.instance.occupants }} #[template(v-if="userDialog.instance.friendCount > 0") ({{ userDialog.instance.friendCount }})] @@ -1780,7 +1780,7 @@ html #[i.el-icon-check(style="margin-left:10px")] Capacity {{ worldDialog.ref.capacity | commaNumber }} ({{ worldDialog.ref.capacity * 2 | commaNumber }}) div(v-for="room in worldDialog.rooms" :key="room.id") div(style="margin:5px 0") - span.x-link(@click="showLaunchDialog(room.$location.tag)") + span.x-link(@click="showLaunchDialog(room.$location.tag, room.$location.shortName)") span \#{{ room.$location.instanceName }} {{ room.$location.accessType }} span.flags(v-if="room.$location.region" :class="room.$location.region" style="display:inline-block;margin-left:5px") span.flags(v-else class="us" style="display:inline-block;margin-left:5px") @@ -2096,7 +2096,7 @@ html el-form-item(label="World ID") el-input(v-model="newInstanceDialog.worldId" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()") el-form-item(label="Instance ID") - el-input(v-model="newInstanceDialog.instanceName" placeholder="Random" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()") + el-input(v-model="newInstanceDialog.instanceName" placeholder="Random" size="mini") el-form-item(label="Instance Creator") el-select(v-model="newInstanceDialog.userId" clearable placeholder="Choose User" filterable style="width:100%") el-option-group(v-if="API.currentUser" label="ME") @@ -2142,7 +2142,7 @@ html el-form-item(label="URL") el-input(v-model="newInstanceDialog.url" size="mini" readonly @click.native="$event.target.tagName === 'INPUT' && $event.target.select()") template(#footer) - el-button(size="small" @click="copyInstanceUrlAndUpdateNewInstanceDialog(newInstanceDialog.url)") Copy URL + el-button(size="small" @click="copyInstanceUrl(newInstanceDialog.location)") Copy URL el-button(size="small" @click="selfInvite(newInstanceDialog.location)") Self Invite el-button(size="small" @click="showInviteDialog(newInstanceDialog.location)" :disabled="(newInstanceDialog.accessType === 'friends' || newInstanceDialog.accessType === 'invite') && newInstanceDialog.userId !== API.currentUser.id") Invite el-button(type="primary" size="small" @click="showLaunchDialog(newInstanceDialog.location)") Launch @@ -2280,18 +2280,21 @@ html //- dialog: launch el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="launchDialog" :visible.sync="launchDialog.visible" title="Launch" width="450px") - div(v-if="launchDialog.shortUrl") - el-tooltip(placement="top" content="Copy to clipboard" :disabled="hideTooltips") - el-button(@click="copyInstanceUrl(launchDialog.shortUrl)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle) - span(v-text="launchDialog.shortUrl" style="word-break:break-all;font-size:12px") - div(style="margin-top:10px") - el-tooltip(placement="top" content="Copy to clipboard" :disabled="hideTooltips") - el-button(@click="copyInstanceUrl(launchDialog.url)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle) - span(v-text="launchDialog.url" style="word-break:break-all;font-size:12px") - div(style="margin-top:10px") - el-tooltip(placement="top" content="Copy to clipboard" :disabled="hideTooltips") - el-button(@click="copyInstanceUrl(launchDialog.location)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle) - span(v-text="launchDialog.location" style="word-break:break-all;font-size:12px") + el-form(:model="launchDialog" label-width="80px") + el-form-item(label="URL") + el-input(v-model="launchDialog.url" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()" style="width:260px") + el-tooltip(placement="top" content="Copy to clipboard" :disabled="hideTooltips") + el-button(@click="copyInstanceMessage(launchDialog.url)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle) + el-form-item(v-if="launchDialog.shortUrl" label="Short URL") + el-tooltip(placement="top" style="margin-left:5px" content="Short URL's expire after a set period of time") + i.el-icon-warning + el-input(v-model="launchDialog.shortUrl" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()" style="width:241px") + el-tooltip(placement="top" content="Copy to clipboard" :disabled="hideTooltips") + el-button(@click="copyInstanceMessage(launchDialog.shortUrl)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle) + el-form-item(label="Location") + el-input(v-model="launchDialog.location" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()" style="width:260px") + el-tooltip(placement="top" content="Copy to clipboard" :disabled="hideTooltips") + el-button(@click="copyInstanceMessage(launchDialog.location)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle) template(#footer) el-checkbox(v-model="launchDialog.desktop" style="float:left;margin-top:5px") Start as Desktop (No VR) el-button(size="small" @click="showPreviousInstanceInfoDialog(launchDialog.location)") Info