diff --git a/AppApi.cs b/AppApi.cs index 9cc8168f..6e9b31dd 100644 --- a/AppApi.cs +++ b/AppApi.cs @@ -315,7 +315,7 @@ namespace VRCX System.Environment.Exit(0); } - public bool CheckForUpdateZip() + public bool CheckForUpdateExe() { if (File.Exists(Path.Combine(Program.AppDataDirectory, "update.exe"))) return true; diff --git a/html/src/app.js b/html/src/app.js index 2b35ef8c..5313ebf9 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -9457,7 +9457,7 @@ speechSynthesis.getVoices(); Location: 'Off', OnPlayerJoined: 'VIP', OnPlayerLeft: 'VIP', - OnPlayerJoining: 'Off', + OnPlayerJoining: 'VIP', Online: 'VIP', Offline: 'VIP', GPS: 'Off', @@ -10134,7 +10134,9 @@ speechSynthesis.getVoices(); ownerId: '', avatarName: '', fileCreatedAt: '' - } + }, + lastSeen: '', + joinCount: 0 }; $app.watch['userDialog.memo'] = function () { @@ -10334,6 +10336,8 @@ speechSynthesis.getVoices(); D.avatars = []; D.worlds = []; D.instance = {}; + D.lastSeen = ''; + D.joinCount = 0; API.getCachedUser({ userId }) @@ -10414,6 +10418,16 @@ speechSynthesis.getVoices(); instanceId: L.instanceId }); } + database.getLastSeen(D.ref).then((ref1) => { + if (ref1.userId === D.id) { + D.lastSeen = ref1.created_at; + } + }); + database.getJoinCount(D.ref).then((ref2) => { + if (ref2.userId === D.id) { + D.joinCount = ref2.joinCount; + } + }); } return args; }); @@ -10914,7 +10928,9 @@ speechSynthesis.getVoices(); fileSize: '', inCache: false, cacheSize: 0, - cacheLocked: false + cacheLocked: false, + lastVisit: '', + visitCount: 0 }; API.$on('LOGOUT', function () { @@ -11011,6 +11027,18 @@ speechSynthesis.getVoices(); D.cacheSize = 0; D.cacheLocked = false; D.rooms = []; + D.lastVisit = ''; + D.visitCount = ''; + database.getLastVisit(D.id).then((ref) => { + if (ref.worldId === D.id) { + D.lastVisit = ref.created_at; + } + }); + database.getVisitCount(D.id).then((ref) => { + if (ref.worldId === D.id) { + D.visitCount = ref.visitCount; + } + }); API.getCachedWorld({ worldId: L.worldId }) @@ -15419,7 +15447,7 @@ speechSynthesis.getVoices(); this.$nextTick(() => adjustDialogZ(this.$refs.VRCXUpdateDialog.$el)); var D = this.VRCXUpdateDialog; D.visible = true; - D.updatePending = await AppApi.CheckForUpdateZip(); + D.updatePending = await AppApi.CheckForUpdateExe(); this.loadBranchVersions(); }; @@ -15510,7 +15538,7 @@ speechSynthesis.getVoices(); }; $app.methods.checkForVRCXUpdate = async function () { - if (await AppApi.CheckForUpdateZip()) { + if (await AppApi.CheckForUpdateExe()) { return; } var url = this.branches[this.branch].urlLatest; @@ -15653,6 +15681,24 @@ speechSynthesis.getVoices(); API.cachedAvatarNames = new Map(); }; + $app.data.sqliteTableSizes = {}; + + $app.methods.getSqliteTableSizes = async function () { + this.sqliteTableSizes = { + gps: await database.getGpsTableSize(), + status: await database.getStatusTableSize(), + avatar: await database.getAvatarTableSize(), + onlineOffline: await database.getOnlineOfflineTableSize(), + friendLogHistory: await database.getFriendLogHistoryTableSize(), + notification: await database.getNotificationTableSize(), + location: await database.getLocationTableSize(), + joinLeave: await database.getJoinLeaveTableSize(), + portalSpawn: await database.getPortalSpawnTableSize(), + videoPlay: await database.getVideoPlayTableSize(), + event: await database.getEventTableSize() + }; + }; + $app.methods.ipcEvent = function (json) { try { var data = JSON.parse(json); diff --git a/html/src/index.pug b/html/src/index.pug index d1918d8c..bdb63e6f 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -963,6 +963,32 @@ html el-button(size="small" icon="el-icon-delete-solid" @click="clearVRCXCache") Clear Cache div.options-container-item el-button(size="small" icon="el-icon-tickets" @click="showConsole") Show Console + div.options-container + span.header SQLite Table Size + div.options-container-item + el-button(size="small" icon="el-icon-refresh" @click="getSqliteTableSizes") Refresh + div.options-container-item + span.name GPS: #[span(v-text="sqliteTableSizes.gps")] + div.options-container-item + span.name Status: #[span(v-text="sqliteTableSizes.status")] + div.options-container-item + span.name Avatar: #[span(v-text="sqliteTableSizes.avatar")] + div.options-container-item + span.name Online/Offline: #[span(v-text="sqliteTableSizes.onlineOffline")] + div.options-container-item + span.name Friend Log History: #[span(v-text="sqliteTableSizes.friendLogHistory")] + div.options-container-item + span.name Notifications: #[span(v-text="sqliteTableSizes.notification")] + div.options-container-item + span.name Location: #[span(v-text="sqliteTableSizes.location")] + div.options-container-item + span.name Join/Leave: #[span(v-text="sqliteTableSizes.joinLeave")] + div.options-container-item + span.name Portal Spawn: #[span(v-text="sqliteTableSizes.portalSpawn")] + div.options-container-item + span.name Video Play: #[span(v-text="sqliteTableSizes.videoPlay")] + div.options-container-item + span.name Event: #[span(v-text="sqliteTableSizes.event")] div.options-container(style="margin-top:45px;border-top:1px solid #eee;padding-top:30px") span.header Legal Notice div.options-container-item @@ -1200,9 +1226,12 @@ html img(:src="getFaviconUrl(link)" style="width:16px;height:16px;vertical-align:middle;margin-right:5px;cursor:pointer" @click.stop="openExternalLink(link)") .x-friend-item(style="cursor:default") .detail - span.name Avatar Copying - span.extra(v-if="userDialog.ref.allowAvatarCopying" style="color:#67C23A") Allow - span.extra(v-else style="color:#F56C6C") Deny + span.name Last Seen + span.extra {{ userDialog.lastSeen | formatDate('YYYY-MM-DD HH24:MI:SS') || '-' }} + .x-friend-item(style="cursor:default") + .detail + span.name Join Count + span.extra(v-text="userDialog.joinCount") .x-friend-item(style="cursor:default") .detail span.name(v-if="userDialog.ref.state === 'online' && userDialog.ref.$online_for") Online For @@ -1216,6 +1245,11 @@ html .detail span.name Date Joined span.extra(v-text="userDialog.ref.date_joined") + .x-friend-item(style="cursor:default") + .detail + span.name Avatar Copying + span.extra(v-if="userDialog.ref.allowAvatarCopying" style="color:#67C23A") Allow + span.extra(v-else style="color:#F56C6C") Deny .x-friend-item(v-if="userDialog.ref.id === API.currentUser.id && API.currentUser.homeLocation" @click="showWorldDialog(API.currentUser.homeLocation)" style="width:100%") .detail span.name Home Location @@ -1379,7 +1413,7 @@ html .x-friend-item(style="cursor:default") .detail span.name Favorites - span.extra {{ worldDialog.ref.favorites | commaNumber }} + span.extra {{ worldDialog.ref.favorites | commaNumber }} ({{ Math.round(((worldDialog.ref.favorites - worldDialog.ref.visits) / worldDialog.ref.visits * 100 + 100) * 100) / 100 }}%) .x-friend-item(style="cursor:default") .detail span.name Visits @@ -1412,6 +1446,14 @@ html .detail span.name Platform span.extra(v-text="worldDialogPlatform") + .x-friend-item(style="cursor:default") + .detail + span.name Last Visit + span.extra {{ worldDialog.lastVisit | formatDate('YYYY-MM-DD HH24:MI:SS') || '-' }} + .x-friend-item(style="cursor:default") + .detail + span.name Visit Count + span.extra(v-text="worldDialog.visitCount") el-tab-pane(label="JSON") el-button(type="default" @click="refreshWorldDialogTreeData()" size="mini" icon="el-icon-refresh" circle) el-tree(:data="worldDialog.treeData" style="margin-top:5px;font-size:12px") diff --git a/html/src/repository/database.js b/html/src/repository/database.js index dacfbb40..da9a1eef 100644 --- a/html/src/repository/database.js +++ b/html/src/repository/database.js @@ -133,7 +133,8 @@ class Database { sqliteService.executeNonQuery('COMMIT'); } - async getMemo(userId) { + async getMemo(input) { + var userId = input.replaceAll("'", ''); var row = {}; await sqliteService.execute((dbRow) => { row = { @@ -625,6 +626,170 @@ class Database { } ); } + + async getGpsTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM ${Database.userId}_feed_gps`); + return size; + } + + async getStatusTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM ${Database.userId}_feed_status`); + return size; + } + + async getAvatarTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM ${Database.userId}_feed_avatar`); + return size; + } + + async getOnlineOfflineTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM ${Database.userId}_feed_online_offline`); + return size; + } + + async getFriendLogHistoryTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM ${Database.userId}_friend_log_history`); + return size; + } + + async getNotificationTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM ${Database.userId}_notifications`); + return size; + } + + async getLocationTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM gamelog_location`); + return size; + } + + async getJoinLeaveTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM gamelog_join_leave`); + return size; + } + + async getPortalSpawnTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM gamelog_portal_spawn`); + return size; + } + + async getVideoPlayTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM gamelog_video_play`); + return size; + } + + async getEventTableSize() { + var size = 0; + await sqliteService.execute((row) => { + size = row[0]; + }, `SELECT COUNT(*) FROM gamelog_event`); + return size; + } + + async getLastVisit(input) { + var worldId = input.replaceAll("'", ''); + var ref = { + created_at: '', + worldId: '' + }; + await sqliteService.execute((row) => { + ref = { + created_at: row[0], + worldId: row[1] + }; + }, `SELECT created_at, world_id FROM gamelog_location WHERE world_id = '${worldId}' ORDER BY id DESC LIMIT 1`); + return ref; + } + + async getVisitCount(input) { + var worldId = input.replaceAll("'", ''); + var ref = { + visitCount: '', + worldId: '' + }; + await sqliteService.execute((row) => { + ref = { + visitCount: row[0], + worldId: input + }; + }, `SELECT COUNT(*) FROM gamelog_location WHERE world_id = '${worldId}'`); + return ref; + } + + async getLastSeen(input) { + var userId = input.id.replaceAll("'", ''); + var displayName = input.displayName.replaceAll("'", "''"); + var ref = { + created_at: '', + userId: '' + }; + await sqliteService.execute((row) => { + if (row[1]) { + ref = { + created_at: row[0], + userId: row[1] + }; + } else { + ref = { + created_at: row[0], + userId + }; + } + }, `SELECT created_at, user_id FROM gamelog_join_leave WHERE user_id = '${userId}' OR display_name = '${displayName}' ORDER BY id DESC LIMIT 1`); + return ref; + } + + async getJoinCount(input) { + var userId = input.id.replaceAll("'", ''); + var displayName = input.displayName.replaceAll("'", "''"); + var ref = { + joinCount: '', + userId: '' + }; + await sqliteService.execute((row) => { + if (row[1]) { + ref = { + joinCount: row[0], + userId: row[1] + }; + } else { + ref = { + joinCount: row[0], + userId + }; + } + }, `SELECT COUNT(*) FROM gamelog_join_leave WHERE user_id = '${userId}' OR display_name = '${displayName}'`); + return ref; + } } var self = new Database();