diff --git a/html/src/app.js b/html/src/app.js index 2e7f5dc8..915c1ce8 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -1458,12 +1458,9 @@ speechSynthesis.getVoices(); // ...json }; - if ( - !json.isFriend && - $app.lastLocation.playerList.has(json.displayName) - ) { + if ($app.lastLocation.playerList.has(json.displayName)) { + // update $location_at from instance join time var player = $app.lastLocation.playerList.get(json.displayName); - ref.location = 'offline'; ref.$location_at = player.joinTime; ref.$online_for = player.joinTime; } @@ -7512,7 +7509,12 @@ speechSynthesis.getVoices(); if (configRepository.getBool(`friendLogInit_${args.json.id}`)) { await $app.getFriendLog(); } else { - await $app.initFriendLog(args.json.id); + try { + await $app.initFriendLog(args.json.id); + } catch (err) { + this.logout(); + throw err; + } } $app.getAllMemos(); if ($app.randomUserColours) { @@ -8206,27 +8208,36 @@ speechSynthesis.getVoices(); database.addGamelogLocationToDatabase(entry); break; case 'player-joined': + var joinTime = Date.parse(gameLog.dt); var userMap = { displayName: gameLog.userDisplayName, userId, - joinTime: Date.parse(gameLog.dt) + joinTime }; this.lastLocation.playerList.set( gameLog.userDisplayName, userMap ); if (userId) { - if (this.friends.has(userId)) { + var ref = API.cachedUsers.get(userId); + if (userId === API.currentUser.id) { + // skip + } else if (this.friends.has(userId)) { this.lastLocation.friendList.set( gameLog.userDisplayName, userMap ); - } else { - var ref = API.cachedUsers.get(userId); - if (typeof ref !== 'undefined') { - var joinTime = Date.parse(gameLog.dt); + if ( + ref.location !== this.lastLocation.location && + ref.travelingToLocation !== + this.lastLocation.location + ) { + // fix $location_at with private ref.$location_at = joinTime; } + } else if (typeof ref !== 'undefined') { + // set $location_at to join time if user isn't a friend + ref.$location_at = joinTime; } } this.updateVRLastLocation(); @@ -10980,8 +10991,7 @@ speechSynthesis.getVoices(); }; $app.methods.getFriendLog = async function () { - await database.cleanLegendFromFriendLog(); // fix database spam crap - await database.fixGameLogTraveling(); // fix past bug with incorrect gameLog locations + await this.updateDatabaseVersion(); var friendLogCurrentArray = await database.getFriendLogCurrent(); for (var friend of friendLogCurrentArray) { this.friendLog.set(friend.userId, friend); @@ -13572,19 +13582,6 @@ speechSynthesis.getVoices(); if (addUser) { var ref = API.cachedUsers.get(player.userId); if (typeof ref !== 'undefined') { - if ( - !ref.isFriend || - ref.location !== this.lastLocation.location - ) { - // fix $location_at - var {joinTime} = this.lastLocation.playerList.get( - ref.displayName - ); - if (!joinTime) { - joinTime = Date.now(); - } - ref.$location_at = joinTime; - } pushUser(ref); } else { var {joinTime} = this.lastLocation.playerList.get( @@ -19905,6 +19902,22 @@ speechSynthesis.getVoices(); database.clearAvatarHistory(); }; + $app.data.databaseVersion = configRepository.getInt('VRCX_databaseVersion'); + + $app.methods.updateDatabaseVersion = async function () { + var databaseVersion = 1; + if (this.databaseVersion !== databaseVersion) { + console.log('Updating database...'); + await database.cleanLegendFromFriendLog(); // fix friendLog spammed with crap + await database.fixGameLogTraveling(); // fix bug with gameLog location being set as traveling + await database.fixNegativeGPS(); // fix GPS being a negative value due to VRCX bug with traveling + await database.fixBrokenLeaveEntries(); // fix user instance timer being higher than current user location timer + this.databaseVersion = databaseVersion; + configRepository.setInt('VRCX_databaseVersion', databaseVersion); + console.log('Database update complete.'); + } + }; + $app = new Vue($app); window.$app = $app; })(); diff --git a/html/src/index.pug b/html/src/index.pug index e78e8c1f..00ff44c7 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -1361,9 +1361,11 @@ html el-tooltip(placement="bottom" content="Refresh friends" :disabled="hideTooltips") el-button(type="default" @click="API.closeWebSocket(); API.getCurrentUser(); API.refreshFriends()" :loading="API.isRefreshFriendsLoading" size="mini" icon="el-icon-refresh" circle style="margin-right:10px") .x-friend-list(style="padding-bottom:10px") - .x-friend-group + .x-friend-group(style="padding:5px 0 0") + span FRIENDS―{{ onlineFriendCount }}/{{ friends.size }} + .x-friend-group(style="padding:10px 0 5px") i.el-icon-arrow-right(:class="{ rotate: isFriendsGroupMe }") - span.x-link(@click="isFriendsGroupMe = !isFriendsGroupMe" style="margin-left:5px") ME―{{ onlineFriendCount }}/{{ friends.size }} + span.x-link(@click="isFriendsGroupMe = !isFriendsGroupMe" style="margin-left:5px") ME div(v-show="isFriendsGroupMe") .x-friend-item(:key="API.currentUser.id" @click="showUserDialog(API.currentUser.id)") .avatar(:class="userStatusClass(API.currentUser)") @@ -2819,7 +2821,7 @@ html br el-button-group(style="padding-bottom:10px;padding-top:10px") el-button(type="default" size="small" @click="displayPreviousImages('Avatar', 'Change')" icon="el-icon-refresh") Refresh - el-button(type="default" size="small" @click="uploadAvatarImage" icon="el-icon-upload2") Upload Image (1200x900) + el-button(type="default" size="small" @click="uploadAvatarImage" icon="el-icon-upload2") Upload Image //- el-button(type="default" size="small" @click="deleteAvatarImage" icon="el-icon-delete") Delete Latest Image br div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file") @@ -2834,7 +2836,7 @@ html br el-button-group(style="padding-bottom:10px;padding-top:10px") el-button(type="default" size="small" @click="displayPreviousImages('World', 'Change')" icon="el-icon-refresh") Refresh - el-button(type="default" size="small" @click="uploadWorldImage" icon="el-icon-upload2") Upload Image (1200x900) + el-button(type="default" size="small" @click="uploadWorldImage" icon="el-icon-upload2") Upload Image //- el-button(type="default" size="small" @click="deleteWorldImage" icon="el-icon-delete") Delete Latest Image br div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file") diff --git a/html/src/repository/database.js b/html/src/repository/database.js index a6b29595..ab821c33 100644 --- a/html/src/repository/database.js +++ b/html/src/repository/database.js @@ -1565,6 +1565,67 @@ class Database { ); }); } + + async fixNegativeGPS() { + var gpsTables = []; + await sqliteService.execute((dbRow) => { + gpsTables.push(dbRow[0]); + }, `SELECT name FROM sqlite_schema WHERE type='table' AND name LIKE '%_gps'`); + gpsTables.forEach((tableName) => { + sqliteService.executeNonQuery( + `UPDATE ${tableName} SET time = 0 WHERE time < 0` + ); + }); + } + + async getGameLogInstancesTime() { + var instances = new Map(); + await sqliteService.execute((dbRow) => { + var time = 0; + var location = dbRow[0]; + if (dbRow[1]) { + time = dbRow[1]; + } + var ref = instances.get(location); + if (typeof ref !== 'undefined') { + time += ref; + } + instances.set(location, time); + }, 'SELECT location, time FROM gamelog_location'); + return instances; + } + + async getBrokenLeaveEntries() { + var instances = await this.getGameLogInstancesTime(); + var badEntries = []; + await sqliteService.execute((dbRow) => { + if (typeof dbRow[1] === 'number') { + var ref = instances.get(dbRow[0]); + if (typeof ref !== 'undefined' && dbRow[1] > ref) { + badEntries.push(dbRow[2]); + } + } + }, `SELECT location, time, id FROM gamelog_join_leave WHERE type = 'OnPlayerLeft' AND time > 0`); + return badEntries; + } + + async fixBrokenLeaveEntries() { + var badEntries = await this.getBrokenLeaveEntries(); + var badEntriesList = ''; + var count = badEntries.length; + badEntries.forEach((entry) => { + count--; + if (count === 0) { + badEntriesList = badEntriesList.concat(entry); + } else { + badEntriesList = badEntriesList.concat(`${entry}, `); + } + }); + + sqliteService.executeNonQuery( + `UPDATE gamelog_join_leave SET time = 0 WHERE id IN (${badEntriesList})` + ); + } } var self = new Database();