mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
v2019.11.18
This commit is contained in:
36
VRCX.cs
36
VRCX.cs
@@ -4,7 +4,11 @@
|
|||||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
|
using Microsoft.Win32;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace VRCX
|
namespace VRCX
|
||||||
@@ -39,17 +43,45 @@ namespace VRCX
|
|||||||
return WinApi.FindWindow("UnityWndClass", "VRChat") != IntPtr.Zero;
|
return WinApi.FindWindow("UnityWndClass", "VRChat") != IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartGame(string location)
|
public void StartGame(string location, bool desktop)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
System.Diagnostics.Process.Start("vrchat://launch?id=" + location);
|
using (var key = Registry.ClassesRoot.OpenSubKey(@"VRChat\shell\open\command"))
|
||||||
|
{
|
||||||
|
// "C:\Program Files (x86)\Steam\steamapps\common\VRChat\launch.bat" "C:\Program Files (x86)\Steam\steamapps\common\VRChat" "%1"
|
||||||
|
var match = Regex.Match(key.GetValue(string.Empty) as string, "^\"(.+\\\\VRChat)\\\\launch.bat\"");
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var path = match.Groups[1].Value;
|
||||||
|
var args = new StringBuilder();
|
||||||
|
if (desktop)
|
||||||
|
{
|
||||||
|
args.Append("--no-vr ");
|
||||||
|
}
|
||||||
|
args.Append("\"vrchat://launch?id=");
|
||||||
|
args.Append(location);
|
||||||
|
args.Append('"');
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
WorkingDirectory = path,
|
||||||
|
FileName = path + "\\VRChat.exe",
|
||||||
|
UseShellExecute = false,
|
||||||
|
Arguments = args.ToString()
|
||||||
|
}).Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenRepository()
|
||||||
|
{
|
||||||
|
Process.Start("https://github.com/pypy-vrc/VRCX").Close();
|
||||||
|
}
|
||||||
|
|
||||||
public void ShowVRForm()
|
public void ShowVRForm()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
24
html/app.css
24
html/app.css
@@ -64,6 +64,10 @@ For a copy, see <https://opensource.org/licenses/MIT>.
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-dialog__footer>.el-button+.el-button {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
@@ -135,14 +139,24 @@ body, input, textarea, select, button {
|
|||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-menu-item.is-active::before {
|
||||||
|
position: absolute;
|
||||||
|
content: '';
|
||||||
|
left: 1px;
|
||||||
|
top: 4px;
|
||||||
|
width: 2px;
|
||||||
|
height: 48px;
|
||||||
|
background: #DCDFE6;
|
||||||
|
}
|
||||||
|
|
||||||
.el-menu-item.notify::after {
|
.el-menu-item.notify::after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: '';
|
content: '';
|
||||||
right: 5px;
|
right: 4px;
|
||||||
top: 5px;
|
top: 4px;
|
||||||
width: 5px;
|
width: 6px;
|
||||||
height: 5px;
|
height: 6px;
|
||||||
background: #909399;
|
background: #EBEEF5;
|
||||||
border-radius: 50%
|
border-radius: 50%
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
84
html/app.js
84
html/app.js
@@ -92,10 +92,12 @@ if (window.CefSharp) {
|
|||||||
setInterval(() => VRCXStorage.Flush(), 5 * 60 * 1000);
|
setInterval(() => VRCXStorage.Flush(), 5 * 60 * 1000);
|
||||||
|
|
||||||
Noty.overrideDefaults({
|
Noty.overrideDefaults({
|
||||||
|
/*
|
||||||
animation: {
|
animation: {
|
||||||
open: 'animated bounceInLeft',
|
open: 'animated bounceInLeft',
|
||||||
close: 'animated bounceOutLeft'
|
close: 'animated bounceOutLeft'
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
layout: 'bottomLeft',
|
layout: 'bottomLeft',
|
||||||
theme: 'mint',
|
theme: 'mint',
|
||||||
timeout: 6000
|
timeout: 6000
|
||||||
@@ -825,6 +827,8 @@ if (window.CefSharp) {
|
|||||||
id: ref.id,
|
id: ref.id,
|
||||||
username: '',
|
username: '',
|
||||||
displayName: '',
|
displayName: '',
|
||||||
|
bio: '',
|
||||||
|
bioLinks: [],
|
||||||
pastDisplayNames: [],
|
pastDisplayNames: [],
|
||||||
friends: [],
|
friends: [],
|
||||||
currentAvatarImageUrl: '',
|
currentAvatarImageUrl: '',
|
||||||
@@ -938,6 +942,8 @@ if (window.CefSharp) {
|
|||||||
id: ref.id,
|
id: ref.id,
|
||||||
username: '',
|
username: '',
|
||||||
displayName: '',
|
displayName: '',
|
||||||
|
bio: '',
|
||||||
|
bioLinks: [],
|
||||||
currentAvatarImageUrl: '',
|
currentAvatarImageUrl: '',
|
||||||
currentAvatarThumbnailImageUrl: '',
|
currentAvatarThumbnailImageUrl: '',
|
||||||
status: '',
|
status: '',
|
||||||
@@ -3471,7 +3477,7 @@ if (window.CefSharp) {
|
|||||||
VRCX,
|
VRCX,
|
||||||
nextRefresh: 0,
|
nextRefresh: 0,
|
||||||
isGameRunning: false,
|
isGameRunning: false,
|
||||||
appVersion: '2019.10.31.1',
|
appVersion: 'VRCX 2019.11.18',
|
||||||
latestAppVersion: '',
|
latestAppVersion: '',
|
||||||
ossDialog: false
|
ossDialog: false
|
||||||
},
|
},
|
||||||
@@ -3509,6 +3515,17 @@ if (window.CefSharp) {
|
|||||||
if (json.name &&
|
if (json.name &&
|
||||||
json.published_at) {
|
json.published_at) {
|
||||||
this.latestAppVersion = `${json.name} (${formatDate(json.published_at, 'YYYY-MM-DD HH24:MI:SS')})`;
|
this.latestAppVersion = `${json.name} (${formatDate(json.published_at, 'YYYY-MM-DD HH24:MI:SS')})`;
|
||||||
|
if (json.name > this.appVersion) {
|
||||||
|
new Noty({
|
||||||
|
type: 'info',
|
||||||
|
text: `Update available!!<br>${this.latestAppVersion}`,
|
||||||
|
timeout: false,
|
||||||
|
callbacks: {
|
||||||
|
onClick: () => VRCX.OpenRepository()
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
this.notifyMenu('more');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.latestAppVersion = 'Error occured';
|
this.latestAppVersion = 'Error occured';
|
||||||
}
|
}
|
||||||
@@ -3653,28 +3670,6 @@ if (window.CefSharp) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.showLaunchDialog = function (tag) {
|
|
||||||
var L = API.parseLocation(tag);
|
|
||||||
if (L.worldId) {
|
|
||||||
this.$msgbox({
|
|
||||||
title: 'Launch World',
|
|
||||||
message: `<span style="word-break:break-all;font-size:12px">${escapeTag(`https://vrchat.net/launch?worldId=${encodeURIComponent(L.worldId)}&instanceId=${encodeURIComponent(L.instanceId)}`)}</span>`,
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
distinguishCancelAndClose: true,
|
|
||||||
showCancelButton: true,
|
|
||||||
cancelButtonText: 'Invite',
|
|
||||||
confirmButtonText: 'Launch',
|
|
||||||
callback: (action) => {
|
|
||||||
if (action === 'confirm') {
|
|
||||||
VRCX.StartGame(tag);
|
|
||||||
} else if (action === 'cancel') {
|
|
||||||
$app.showInviteDialog(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.promptTOTP = function () {
|
$app.methods.promptTOTP = function () {
|
||||||
this.$prompt('Enter a numeric code from your authenticator app', 'Two-factor Authentication', {
|
this.$prompt('Enter a numeric code from your authenticator app', 'Two-factor Authentication', {
|
||||||
distinguishCancelAndClose: true,
|
distinguishCancelAndClose: true,
|
||||||
@@ -6834,7 +6829,7 @@ if (window.CefSharp) {
|
|||||||
$app.watch['newInstanceDialog.instanceId'] = updateLocationURL;
|
$app.watch['newInstanceDialog.instanceId'] = updateLocationURL;
|
||||||
|
|
||||||
$app.methods.showNewInstanceDialog = function (tag) {
|
$app.methods.showNewInstanceDialog = function (tag) {
|
||||||
this.$nextTick(() => adjustDialogZ(this.$refs.inviteDialog.$el));
|
this.$nextTick(() => adjustDialogZ(this.$refs.newInstanceDialog.$el));
|
||||||
var L = API.parseLocation(tag);
|
var L = API.parseLocation(tag);
|
||||||
if (!(L.isOffline || L.isPrivate) &&
|
if (!(L.isOffline || L.isPrivate) &&
|
||||||
L.worldId) {
|
L.worldId) {
|
||||||
@@ -6867,6 +6862,47 @@ if (window.CefSharp) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// App: Launch Dialog
|
||||||
|
|
||||||
|
$app.data.launchDialog = {
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
desktop: VRCXStorage.GetBool('launchAsDesktop'),
|
||||||
|
location: '',
|
||||||
|
url: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.watch['launchDialog.desktop'] = function () {
|
||||||
|
VRCXStorage.SetBool('launchAsDesktop', this.launchDialog.desktop);
|
||||||
|
};
|
||||||
|
|
||||||
|
API.$on('LOGOUT', () => {
|
||||||
|
$app.launchDialog.visible = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$app.methods.showLaunchDialog = function (tag) {
|
||||||
|
this.$nextTick(() => adjustDialogZ(this.$refs.launchDialog.$el));
|
||||||
|
var L = API.parseLocation(tag);
|
||||||
|
if (!(L.isOffline || L.isPrivate) &&
|
||||||
|
L.worldId) {
|
||||||
|
var D = this.launchDialog;
|
||||||
|
if (L.instanceId) {
|
||||||
|
D.location = `${L.worldId}:${L.instanceId}`;
|
||||||
|
D.url = `https://vrchat.net/launch?worldId=${encodeURIComponent(L.worldId)}&instanceId=${encodeURIComponent(L.instanceId)}`;
|
||||||
|
} else {
|
||||||
|
D.location = L.worldId;
|
||||||
|
D.url = `https://vrchat.net/launch?worldId=${encodeURIComponent(L.worldId)}`;
|
||||||
|
}
|
||||||
|
D.visible = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.launchGame = function () {
|
||||||
|
var D = this.launchDialog;
|
||||||
|
VRCX.StartGame(D.location, D.desktop);
|
||||||
|
D.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
$app = new Vue($app);
|
$app = new Vue($app);
|
||||||
window.$app = $app;
|
window.$app = $app;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -431,7 +431,7 @@
|
|||||||
<span v-if="scope.row.type === 'DisplayName'">{{ scope.row.previousDisplayName }} <i class="el-icon-right"></i> </span>
|
<span v-if="scope.row.type === 'DisplayName'">{{ scope.row.previousDisplayName }} <i class="el-icon-right"></i> </span>
|
||||||
<span v-text="scope.row.displayName || scope.row.userId" @click="showUserDialog(scope.row.userId)" class="x-link"></span>
|
<span v-text="scope.row.displayName || scope.row.userId" @click="showUserDialog(scope.row.userId)" class="x-link"></span>
|
||||||
<template v-if="scope.row.type === 'TrustLevel'">
|
<template v-if="scope.row.type === 'TrustLevel'">
|
||||||
<br/><span>({{ scope.row.previousTrustLevel }} <i class="el-icon-right"></i> {{ scope.row.trustLevel }})</span>
|
<br><span>({{ scope.row.previousTrustLevel }} <i class="el-icon-right"></i> {{ scope.row.trustLevel }})</span>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -549,7 +549,7 @@
|
|||||||
<span v-else class="extra">Click to refresh</span>
|
<span v-else class="extra">Click to refresh</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="x-friend-item">
|
<div class="x-friend-item" @click="VRCX.OpenRepository()">
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<span class="name">Repository URL</span>
|
<span class="name">Repository URL</span>
|
||||||
<span class="extra">https://github.com/pypy-vrc/VRCX</span>
|
<span class="extra">https://github.com/pypy-vrc/VRCX</span>
|
||||||
@@ -669,7 +669,7 @@
|
|||||||
<div class="x-friend-item">
|
<div class="x-friend-item">
|
||||||
<div class="detail" @click="API.getVisits()">
|
<div class="detail" @click="API.getVisits()">
|
||||||
<span class="name">Online Users</span>
|
<span class="name">Online Users</span>
|
||||||
<span v-if="visits" class="extra">{{visits}} Users online.</span>
|
<span v-if="visits" class="extra">{{visits}} users online.</span>
|
||||||
<span v-else class="extra">Click to refresh</span>
|
<span v-else class="extra">Click to refresh</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1417,7 +1417,17 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button size="small" @click="makeHome(newInstanceDialog.location)">Make Home</el-button>
|
<el-button size="small" @click="makeHome(newInstanceDialog.location)">Make Home</el-button>
|
||||||
<el-button size="small" @click="showInviteDialog(newInstanceDialog.location)">Invite</el-button>
|
<el-button size="small" @click="showInviteDialog(newInstanceDialog.location)">Invite</el-button>
|
||||||
<el-button type="primary" size="small" @click="VRCX.StartGame(newInstanceDialog.location)">Launch</el-button>
|
<el-button type="primary" size="small" @click="showLaunchDialog(newInstanceDialog.location)">Launch</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- dialog: launch -->
|
||||||
|
<el-dialog ref="launchDialog" :visible.sync="launchDialog.visible" title="Launch" width="400px" class="x-dialog">
|
||||||
|
<div><span v-text="launchDialog.url" style="word-break:break-all;font-size:12px"></span></div>
|
||||||
|
<template #footer>
|
||||||
|
<el-checkbox v-model="launchDialog.desktop" style="float:left;margin-top:5px">Start as Desktop (No VR)</el-checkbox>
|
||||||
|
<el-button size="small" @click="showInviteDialog(launchDialog.location)">Invite</el-button>
|
||||||
|
<el-button type="primary" size="small" @click="launchGame()">Launch</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user