mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 06:56:04 +02:00
Restore friend order
This commit is contained in:
+44
-51
@@ -52,6 +52,7 @@ import _memos from './classes/memos.js';
|
|||||||
import _languages from './classes/languages.js';
|
import _languages from './classes/languages.js';
|
||||||
import _groups from './classes/groups.js';
|
import _groups from './classes/groups.js';
|
||||||
import _vrcRegistry from './classes/vrcRegistry.js';
|
import _vrcRegistry from './classes/vrcRegistry.js';
|
||||||
|
import _restoreFriendOrder from './classes/restoreFriendOrder.js';
|
||||||
|
|
||||||
// API classes
|
// API classes
|
||||||
import _config from './classes/API/config.js';
|
import _config from './classes/API/config.js';
|
||||||
@@ -116,7 +117,8 @@ speechSynthesis.getVoices();
|
|||||||
config: new _config($app, API, $t),
|
config: new _config($app, API, $t),
|
||||||
languages: new _languages($app, API, $t),
|
languages: new _languages($app, API, $t),
|
||||||
groups: new _groups($app, API, $t),
|
groups: new _groups($app, API, $t),
|
||||||
vrcRegistry: new _vrcRegistry($app, API, $t)
|
vrcRegistry: new _vrcRegistry($app, API, $t),
|
||||||
|
restoreFriendOrder: new _restoreFriendOrder($app, API, $t)
|
||||||
};
|
};
|
||||||
|
|
||||||
await configRepository.init();
|
await configRepository.init();
|
||||||
@@ -570,6 +572,7 @@ speechSynthesis.getVoices();
|
|||||||
$previousLocation: '',
|
$previousLocation: '',
|
||||||
$customTag: '',
|
$customTag: '',
|
||||||
$customTagColour: '',
|
$customTagColour: '',
|
||||||
|
$friendNumber: 0,
|
||||||
//
|
//
|
||||||
...json
|
...json
|
||||||
};
|
};
|
||||||
@@ -4144,7 +4147,7 @@ speechSynthesis.getVoices();
|
|||||||
|
|
||||||
$app.data.friends = new Map();
|
$app.data.friends = new Map();
|
||||||
$app.data.pendingActiveFriends = new Set();
|
$app.data.pendingActiveFriends = new Set();
|
||||||
$app.data.friendsNo = 0;
|
$app.data.friendNumber = 0;
|
||||||
$app.data.isFriendsGroupMe = true;
|
$app.data.isFriendsGroupMe = true;
|
||||||
$app.data.isVIPFriends = true;
|
$app.data.isVIPFriends = true;
|
||||||
$app.data.isOnlineFriends = true;
|
$app.data.isOnlineFriends = true;
|
||||||
@@ -4251,7 +4254,7 @@ speechSynthesis.getVoices();
|
|||||||
API.$on('LOGIN', function () {
|
API.$on('LOGIN', function () {
|
||||||
$app.friends.clear();
|
$app.friends.clear();
|
||||||
$app.pendingActiveFriends.clear();
|
$app.pendingActiveFriends.clear();
|
||||||
$app.friendsNo = 0;
|
$app.friendNumber = 0;
|
||||||
$app.isVIPFriends = true;
|
$app.isVIPFriends = true;
|
||||||
$app.isOnlineFriends = true;
|
$app.isOnlineFriends = true;
|
||||||
$app.isActiveFriends = true;
|
$app.isActiveFriends = true;
|
||||||
@@ -4342,40 +4345,6 @@ speechSynthesis.getVoices();
|
|||||||
this.deleteFriend(id);
|
this.deleteFriend(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.saveFriendOrder();
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.saveFriendOrder = async function () {
|
|
||||||
var currentTime = Date.now();
|
|
||||||
var lastStoreTime = await configRepository.getString(
|
|
||||||
`VRCX_lastStoreTime_${API.currentUser.id}`,
|
|
||||||
''
|
|
||||||
);
|
|
||||||
// store once every week
|
|
||||||
if (lastStoreTime && currentTime - lastStoreTime < 604800000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var storedData = {};
|
|
||||||
try {
|
|
||||||
var data = await configRepository.getString(
|
|
||||||
`VRCX_friendOrder_${API.currentUser.id}`
|
|
||||||
);
|
|
||||||
if (data) {
|
|
||||||
var storedData = JSON.parse(data);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
storedData[currentTime] = Array.from(this.friends.keys());
|
|
||||||
await configRepository.setString(
|
|
||||||
`VRCX_friendOrder_${API.currentUser.id}`,
|
|
||||||
JSON.stringify(storedData)
|
|
||||||
);
|
|
||||||
await configRepository.setString(
|
|
||||||
`VRCX_lastStoreTime_${API.currentUser.id}`,
|
|
||||||
currentTime
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.addFriend = function (id, state) {
|
$app.methods.addFriend = function (id, state) {
|
||||||
@@ -4395,7 +4364,6 @@ speechSynthesis.getVoices();
|
|||||||
isVIP,
|
isVIP,
|
||||||
ref,
|
ref,
|
||||||
name,
|
name,
|
||||||
no: ++this.friendsNo,
|
|
||||||
memo: '',
|
memo: '',
|
||||||
pendingOffline: false,
|
pendingOffline: false,
|
||||||
pendingOfflineTime: '',
|
pendingOfflineTime: '',
|
||||||
@@ -7088,7 +7056,8 @@ speechSynthesis.getVoices();
|
|||||||
var row = {
|
var row = {
|
||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
trustLevel: ref.$trustLevel
|
trustLevel: ref.$trustLevel,
|
||||||
|
friendNumber: 0
|
||||||
};
|
};
|
||||||
this.friendLog.set(friend.id, row);
|
this.friendLog.set(friend.id, row);
|
||||||
sqlValues.unshift(row);
|
sqlValues.unshift(row);
|
||||||
@@ -7110,6 +7079,11 @@ speechSynthesis.getVoices();
|
|||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.getFriendLog = async function (currentUser) {
|
$app.methods.getFriendLog = async function (currentUser) {
|
||||||
|
this.friendNumber = await configRepository.getInt(
|
||||||
|
`VRCX_friendNumber_${currentUser.id}`,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
var friendLogCurrentArray = await database.getFriendLogCurrent();
|
var friendLogCurrentArray = await database.getFriendLogCurrent();
|
||||||
for (var friend of friendLogCurrentArray) {
|
for (var friend of friendLogCurrentArray) {
|
||||||
this.friendLog.set(friend.userId, friend);
|
this.friendLog.set(friend.userId, friend);
|
||||||
@@ -7118,7 +7092,9 @@ speechSynthesis.getVoices();
|
|||||||
this.friendLogTable.data = await database.getFriendLogHistory();
|
this.friendLogTable.data = await database.getFriendLogHistory();
|
||||||
this.refreshFriends(currentUser, true);
|
this.refreshFriends(currentUser, true);
|
||||||
await API.refreshFriends();
|
await API.refreshFriends();
|
||||||
|
await this.tryRestoreFriendNumber();
|
||||||
this.friendLogInitStatus = true;
|
this.friendLogInitStatus = true;
|
||||||
|
|
||||||
// check for friend/name/rank change AFTER friendLogInitStatus is set
|
// check for friend/name/rank change AFTER friendLogInitStatus is set
|
||||||
for (var friend of friendLogCurrentArray) {
|
for (var friend of friendLogCurrentArray) {
|
||||||
var ref = API.cachedUsers.get(friend.userId);
|
var ref = API.cachedUsers.get(friend.userId);
|
||||||
@@ -7154,12 +7130,21 @@ speechSynthesis.getVoices();
|
|||||||
userId: id
|
userId: id
|
||||||
}).then((args) => {
|
}).then((args) => {
|
||||||
if (args.json.isFriend && !this.friendLog.has(id)) {
|
if (args.json.isFriend && !this.friendLog.has(id)) {
|
||||||
|
if (this.friendNumber === 0) {
|
||||||
|
this.friendNumber = this.friends.size;
|
||||||
|
}
|
||||||
|
ref.$friendNumber = ++this.friendNumber;
|
||||||
|
configRepository.setInt(
|
||||||
|
`VRCX_friendNumber_${API.currentUser.id}`,
|
||||||
|
this.friendNumber
|
||||||
|
);
|
||||||
this.addFriend(id, ref.state);
|
this.addFriend(id, ref.state);
|
||||||
var friendLogHistory = {
|
var friendLogHistory = {
|
||||||
created_at: new Date().toJSON(),
|
created_at: new Date().toJSON(),
|
||||||
type: 'Friend',
|
type: 'Friend',
|
||||||
userId: id,
|
userId: id,
|
||||||
displayName: ref.displayName
|
displayName: ref.displayName,
|
||||||
|
friendNumber: ref.$friendNumber
|
||||||
};
|
};
|
||||||
this.friendLogTable.data.push(friendLogHistory);
|
this.friendLogTable.data.push(friendLogHistory);
|
||||||
database.addFriendLogHistory(friendLogHistory);
|
database.addFriendLogHistory(friendLogHistory);
|
||||||
@@ -7167,7 +7152,8 @@ speechSynthesis.getVoices();
|
|||||||
var friendLogCurrent = {
|
var friendLogCurrent = {
|
||||||
userId: id,
|
userId: id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
trustLevel: ref.$trustLevel
|
trustLevel: ref.$trustLevel,
|
||||||
|
friendNumber: ref.$friendNumber
|
||||||
};
|
};
|
||||||
this.friendLog.set(id, friendLogCurrent);
|
this.friendLog.set(id, friendLogCurrent);
|
||||||
database.setFriendLogCurrent(friendLogCurrent);
|
database.setFriendLogCurrent(friendLogCurrent);
|
||||||
@@ -7255,7 +7241,8 @@ speechSynthesis.getVoices();
|
|||||||
type: 'DisplayName',
|
type: 'DisplayName',
|
||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
previousDisplayName: ctx.displayName
|
previousDisplayName: ctx.displayName,
|
||||||
|
friendNumber: ref.$friendNumber
|
||||||
};
|
};
|
||||||
this.friendLogTable.data.push(friendLogHistoryDisplayName);
|
this.friendLogTable.data.push(friendLogHistoryDisplayName);
|
||||||
database.addFriendLogHistory(friendLogHistoryDisplayName);
|
database.addFriendLogHistory(friendLogHistoryDisplayName);
|
||||||
@@ -7263,7 +7250,8 @@ speechSynthesis.getVoices();
|
|||||||
var friendLogCurrent = {
|
var friendLogCurrent = {
|
||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
trustLevel: ref.$trustLevel
|
trustLevel: ref.$trustLevel,
|
||||||
|
friendNumber: ref.$friendNumber
|
||||||
};
|
};
|
||||||
this.friendLog.set(ref.id, friendLogCurrent);
|
this.friendLog.set(ref.id, friendLogCurrent);
|
||||||
database.setFriendLogCurrent(friendLogCurrent);
|
database.setFriendLogCurrent(friendLogCurrent);
|
||||||
@@ -7286,7 +7274,8 @@ speechSynthesis.getVoices();
|
|||||||
var friendLogCurrent3 = {
|
var friendLogCurrent3 = {
|
||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
trustLevel: ref.$trustLevel
|
trustLevel: ref.$trustLevel,
|
||||||
|
friendNumber: ref.$friendNumber
|
||||||
};
|
};
|
||||||
this.friendLog.set(ref.id, friendLogCurrent3);
|
this.friendLog.set(ref.id, friendLogCurrent3);
|
||||||
database.setFriendLogCurrent(friendLogCurrent3);
|
database.setFriendLogCurrent(friendLogCurrent3);
|
||||||
@@ -7298,7 +7287,8 @@ speechSynthesis.getVoices();
|
|||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
trustLevel: ref.$trustLevel,
|
trustLevel: ref.$trustLevel,
|
||||||
previousTrustLevel: ctx.trustLevel
|
previousTrustLevel: ctx.trustLevel,
|
||||||
|
friendNumber: ref.$friendNumber
|
||||||
};
|
};
|
||||||
this.friendLogTable.data.push(friendLogHistoryTrustLevel);
|
this.friendLogTable.data.push(friendLogHistoryTrustLevel);
|
||||||
database.addFriendLogHistory(friendLogHistoryTrustLevel);
|
database.addFriendLogHistory(friendLogHistoryTrustLevel);
|
||||||
@@ -7306,7 +7296,8 @@ speechSynthesis.getVoices();
|
|||||||
var friendLogCurrent2 = {
|
var friendLogCurrent2 = {
|
||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
trustLevel: ref.$trustLevel
|
trustLevel: ref.$trustLevel,
|
||||||
|
friendNumber: ref.$friendNumber
|
||||||
};
|
};
|
||||||
this.friendLog.set(ref.id, friendLogCurrent2);
|
this.friendLog.set(ref.id, friendLogCurrent2);
|
||||||
database.setFriendLogCurrent(friendLogCurrent2);
|
database.setFriendLogCurrent(friendLogCurrent2);
|
||||||
@@ -7314,6 +7305,9 @@ speechSynthesis.getVoices();
|
|||||||
this.updateSharedFeed(true);
|
this.updateSharedFeed(true);
|
||||||
}
|
}
|
||||||
ctx.trustLevel = ref.$trustLevel;
|
ctx.trustLevel = ref.$trustLevel;
|
||||||
|
if (ctx.friendNumber) {
|
||||||
|
ref.$friendNumber = ctx.friendNumber;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.deleteFriendLog = function (row) {
|
$app.methods.deleteFriendLog = function (row) {
|
||||||
@@ -7787,7 +7781,7 @@ speechSynthesis.getVoices();
|
|||||||
stripe: true,
|
stripe: true,
|
||||||
size: 'mini',
|
size: 'mini',
|
||||||
defaultSort: {
|
defaultSort: {
|
||||||
prop: '$friendNum',
|
prop: '$friendNumber',
|
||||||
order: 'descending'
|
order: 'descending'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -14828,7 +14822,7 @@ speechSynthesis.getVoices();
|
|||||||
this.stringComparer
|
this.stringComparer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!match && filters.includes('Rank') && ctx.ref.$friendNum) {
|
if (!match && filters.includes('Rank')) {
|
||||||
match = String(ctx.ref.$trustLevel)
|
match = String(ctx.ref.$trustLevel)
|
||||||
.toUpperCase()
|
.toUpperCase()
|
||||||
.includes(query.toUpperCase());
|
.includes(query.toUpperCase());
|
||||||
@@ -14837,7 +14831,6 @@ speechSynthesis.getVoices();
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.ref.$friendNum = ctx.no;
|
|
||||||
results.push(ctx.ref);
|
results.push(ctx.ref);
|
||||||
}
|
}
|
||||||
this.getAllUserStats();
|
this.getAllUserStats();
|
||||||
@@ -19429,7 +19422,7 @@ speechSynthesis.getVoices();
|
|||||||
);
|
);
|
||||||
|
|
||||||
$app.methods.updateDatabaseVersion = async function () {
|
$app.methods.updateDatabaseVersion = async function () {
|
||||||
var databaseVersion = 10;
|
var databaseVersion = 11;
|
||||||
if (this.databaseVersion < databaseVersion) {
|
if (this.databaseVersion < databaseVersion) {
|
||||||
if (this.databaseVersion) {
|
if (this.databaseVersion) {
|
||||||
var msgBox = this.$message({
|
var msgBox = this.$message({
|
||||||
@@ -19448,11 +19441,11 @@ speechSynthesis.getVoices();
|
|||||||
await database.fixNegativeGPS(); // fix GPS being a negative value due to VRCX bug with 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
|
await database.fixBrokenLeaveEntries(); // fix user instance timer being higher than current user location timer
|
||||||
await database.fixBrokenGroupInvites(); // fix notification v2 in wrong table
|
await database.fixBrokenGroupInvites(); // fix notification v2 in wrong table
|
||||||
await database.updateTableForGroupNames(); // alter tables to include group name
|
|
||||||
await database.fixBrokenNotifications(); // fix notifications being null
|
await database.fixBrokenNotifications(); // fix notifications being null
|
||||||
await database.fixBrokenGroupChange(); // fix spam group left & name change
|
await database.fixBrokenGroupChange(); // fix spam group left & name change
|
||||||
await database.fixCancelFriendRequestTypo(); // fix CancelFriendRequst typo
|
await database.fixCancelFriendRequestTypo(); // fix CancelFriendRequst typo
|
||||||
await database.fixBrokenGameLogDisplayNames(); // fix gameLog display names "DisplayName (userId)"
|
await database.fixBrokenGameLogDisplayNames(); // fix gameLog display names "DisplayName (userId)"
|
||||||
|
await database.upgradeDatabaseVersion(); // update database version
|
||||||
await database.vacuum(); // succ
|
await database.vacuum(); // succ
|
||||||
await configRepository.setInt(
|
await configRepository.setInt(
|
||||||
'VRCX_databaseVersion',
|
'VRCX_databaseVersion',
|
||||||
|
|||||||
@@ -0,0 +1,280 @@
|
|||||||
|
import * as workerTimers from 'worker-timers';
|
||||||
|
import configRepository from '../repository/config.js';
|
||||||
|
import database from '../repository/database.js';
|
||||||
|
import { baseClass, $app, API, $t, $utils } from './baseClass.js';
|
||||||
|
|
||||||
|
export default class extends baseClass {
|
||||||
|
constructor(_app, _API, _t) {
|
||||||
|
super(_app, _API, _t);
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
_data = {};
|
||||||
|
|
||||||
|
_methods = {
|
||||||
|
async tryRestoreFriendNumber() {
|
||||||
|
var lastUpdate = await configRepository.getString(
|
||||||
|
`VRCX_lastStoreTime_${API.currentUser.id}`
|
||||||
|
);
|
||||||
|
if (lastUpdate == -1) {
|
||||||
|
// this means the backup was already applied
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var status = false;
|
||||||
|
this.friendNumber = 0;
|
||||||
|
try {
|
||||||
|
if (lastUpdate) {
|
||||||
|
// backup ready to try apply
|
||||||
|
status = await this.restoreFriendNumber();
|
||||||
|
}
|
||||||
|
// needs to be in reverse because we don't know the starting number
|
||||||
|
this.applyFriendLogFriendOrderInReverse();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
if (status) {
|
||||||
|
this.$message({
|
||||||
|
message: 'Friend order restored from backup',
|
||||||
|
type: 'success',
|
||||||
|
duration: 0,
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
|
} else if (this.friendLogTable.data.length > 0) {
|
||||||
|
this.$message({
|
||||||
|
message:
|
||||||
|
'No backup found, friend order partially restored from friendLog',
|
||||||
|
type: 'success',
|
||||||
|
duration: 0,
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await configRepository.setString(
|
||||||
|
`VRCX_lastStoreTime_${API.currentUser.id}`,
|
||||||
|
-1
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
async restoreFriendNumber() {
|
||||||
|
var storedData = null;
|
||||||
|
try {
|
||||||
|
var data = await configRepository.getString(
|
||||||
|
`VRCX_friendOrder_${API.currentUser.id}`
|
||||||
|
);
|
||||||
|
if (data) {
|
||||||
|
var storedData = JSON.parse(data);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
if (!storedData || storedData.length === 0) {
|
||||||
|
var message = 'whomp whomp, no friend order backup found';
|
||||||
|
console.error(message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var friendLogTable = this.getFriendLogFriendOrder();
|
||||||
|
|
||||||
|
// for storedData
|
||||||
|
var machList = [];
|
||||||
|
for (var i = 0; i < Object.keys(storedData).length; i++) {
|
||||||
|
var key = Object.keys(storedData)[i];
|
||||||
|
var value = storedData[key];
|
||||||
|
var item = this.parseFriendOrderBackup(
|
||||||
|
friendLogTable,
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
machList.push(item);
|
||||||
|
}
|
||||||
|
machList.sort((a, b) => b.matches - a.matches);
|
||||||
|
console.log(
|
||||||
|
`friendLog: ${friendLogTable.length} friendOrderBackups:`,
|
||||||
|
machList
|
||||||
|
);
|
||||||
|
|
||||||
|
var bestBackup = machList[0];
|
||||||
|
if (!bestBackup?.isValid) {
|
||||||
|
var message = 'whomp whomp, no valid backup found';
|
||||||
|
console.error(message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.applyFriendOrderBackup(bestBackup.table);
|
||||||
|
this.applyFriendLogFriendOrder();
|
||||||
|
await configRepository.setInt(
|
||||||
|
`VRCX_friendNumber_${API.currentUser.id}`,
|
||||||
|
this.friendNumber
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
getFriendLogFriendOrder() {
|
||||||
|
var friendLogTable = [];
|
||||||
|
for (var i = 0; i < this.friendLogTable.data.length; i++) {
|
||||||
|
var ref = this.friendLogTable.data[i];
|
||||||
|
if (ref.type !== 'Friend') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
friendLogTable.findIndex((x) => x.id === ref.userId) !== -1
|
||||||
|
) {
|
||||||
|
// console.log(
|
||||||
|
// 'ignoring duplicate friend',
|
||||||
|
// ref.displayName,
|
||||||
|
// ref.created_at
|
||||||
|
// );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
friendLogTable.push({
|
||||||
|
id: ref.userId,
|
||||||
|
displayName: ref.displayName,
|
||||||
|
created_at: ref.created_at
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var compareByCreatedAt = function (a, b) {
|
||||||
|
var A = a.created_at;
|
||||||
|
var B = b.created_at;
|
||||||
|
if (A < B) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (A > B) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
friendLogTable.sort(compareByCreatedAt);
|
||||||
|
return friendLogTable;
|
||||||
|
},
|
||||||
|
|
||||||
|
applyFriendLogFriendOrder() {
|
||||||
|
var friendLogTable = this.getFriendLogFriendOrder();
|
||||||
|
if (this.friendNumber === 0) {
|
||||||
|
console.log(
|
||||||
|
'No backup applied, applying friend log in reverse'
|
||||||
|
);
|
||||||
|
// this means no FriendOrderBackup was applied
|
||||||
|
// will need to apply in reverse order instead
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var friendLog of friendLogTable) {
|
||||||
|
var ref = this.friendLog.get(friendLog.id);
|
||||||
|
if (!ref || ref.friendNumber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ref.friendNumber = ++this.friendNumber;
|
||||||
|
this.friendLog.set(ref.userId, ref);
|
||||||
|
database.setFriendLogCurrent(ref);
|
||||||
|
var friendRef = this.friends.get(friendLog.id);
|
||||||
|
if (friendRef?.ref) {
|
||||||
|
friendRef.ref.$friendNumber = ref.friendNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
applyFriendLogFriendOrderInReverse() {
|
||||||
|
this.friendNumber = this.friends.size + 1;
|
||||||
|
var friendLogTable = this.getFriendLogFriendOrder();
|
||||||
|
for (var i = friendLogTable.length - 1; i > -1; i--) {
|
||||||
|
var friendLog = friendLogTable[i];
|
||||||
|
var ref = this.friendLog.get(friendLog.id);
|
||||||
|
if (!ref) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ref.friendNumber) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ref.friendNumber = --this.friendNumber;
|
||||||
|
this.friendLog.set(ref.userId, ref);
|
||||||
|
database.setFriendLogCurrent(ref);
|
||||||
|
var friendRef = this.friends.get(friendLog.id);
|
||||||
|
if (friendRef?.ref) {
|
||||||
|
friendRef.ref.$friendNumber = ref.friendNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('Applied friend order from friendLog');
|
||||||
|
},
|
||||||
|
|
||||||
|
parseFriendOrderBackup(friendLogTable, created_at, backupUserIds) {
|
||||||
|
var backupTable = [];
|
||||||
|
for (var i = 0; i < backupUserIds.length; i++) {
|
||||||
|
var userId = backupUserIds[i];
|
||||||
|
var ctx = this.friends.get(userId);
|
||||||
|
if (ctx) {
|
||||||
|
backupTable.push({
|
||||||
|
id: ctx.id,
|
||||||
|
displayName: ctx.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// var compareTable = [];
|
||||||
|
// compare 2 tables, find max amount of id's in same order
|
||||||
|
var maxMatches = 0;
|
||||||
|
var currentMatches = 0;
|
||||||
|
var backupIndex = 0;
|
||||||
|
for (var i = 0; i < friendLogTable.length; i++) {
|
||||||
|
var isMatch = false;
|
||||||
|
var ref = friendLogTable[i];
|
||||||
|
if (backupIndex <= 0) {
|
||||||
|
backupIndex = backupTable.findIndex((x) => x.id === ref.id);
|
||||||
|
if (backupIndex !== -1) {
|
||||||
|
currentMatches = 1;
|
||||||
|
}
|
||||||
|
} else if (backupTable[backupIndex].id === ref.id) {
|
||||||
|
currentMatches++;
|
||||||
|
isMatch = true;
|
||||||
|
} else {
|
||||||
|
var backupIndex = backupTable.findIndex(
|
||||||
|
(x) => x.id === ref.id
|
||||||
|
);
|
||||||
|
if (backupIndex !== -1) {
|
||||||
|
currentMatches = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (backupIndex === backupTable.length - 1) {
|
||||||
|
backupIndex = 0;
|
||||||
|
} else {
|
||||||
|
backupIndex++;
|
||||||
|
}
|
||||||
|
if (currentMatches > maxMatches) {
|
||||||
|
maxMatches = currentMatches;
|
||||||
|
}
|
||||||
|
// compareTable.push({
|
||||||
|
// id: ref.id,
|
||||||
|
// displayName: ref.displayName,
|
||||||
|
// match: isMatch
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
var lerp = (a, b, alpha) => {
|
||||||
|
return a + alpha * (b - a);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
matches: parseFloat(`${maxMatches}.${created_at}`),
|
||||||
|
table: backupUserIds,
|
||||||
|
isValid: maxMatches > lerp(4, 10, backupTable.length / 1000) // pls no collisions
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
applyFriendOrderBackup(userIdOrder) {
|
||||||
|
for (var i = 0; i < userIdOrder.length; i++) {
|
||||||
|
var userId = userIdOrder[i];
|
||||||
|
var ctx = this.friends.get(userId);
|
||||||
|
var ref = ctx?.ref;
|
||||||
|
if (!ref || ref.$friendNumber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var friendLogCurrent = {
|
||||||
|
userId,
|
||||||
|
displayName: ref.displayName,
|
||||||
|
trustLevel: ref.$trustLevel,
|
||||||
|
friendNumber: i + 1
|
||||||
|
};
|
||||||
|
this.friendLog.set(userId, friendLogCurrent);
|
||||||
|
database.setFriendLogCurrent(friendLogCurrent);
|
||||||
|
this.friendNumber = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -46,7 +46,7 @@ mixin userDialog()
|
|||||||
span(style="display:block;text-align:center;font-family:monospace") {{ API.currentUser.username | textToHex }}
|
span(style="display:block;text-align:center;font-family:monospace") {{ API.currentUser.username | textToHex }}
|
||||||
div(style="margin-top:5px")
|
div(style="margin-top:5px")
|
||||||
el-tag.name(type="info" effect="plain" size="mini" :class="userDialog.ref.$trustClass" v-text="userDialog.ref.$trustLevel" style="margin-right:5px;margin-top:5px")
|
el-tag.name(type="info" effect="plain" size="mini" :class="userDialog.ref.$trustClass" v-text="userDialog.ref.$trustLevel" style="margin-right:5px;margin-top:5px")
|
||||||
el-tag.x-tag-friend(v-if="userDialog.isFriend && userDialog.friend" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.user.tags.friend_no', { number: userDialog.friend.no }) }}
|
el-tag.x-tag-friend(v-if="userDialog.isFriend && userDialog.friend" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.user.tags.friend_no', { number: userDialog.ref.$friendNumber ? userDialog.ref.$friendNumber : "?" }) }}
|
||||||
el-tag.x-tag-troll(v-if="userDialog.ref.$isTroll" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Nuisance
|
el-tag.x-tag-troll(v-if="userDialog.ref.$isTroll" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Nuisance
|
||||||
el-tag.x-tag-troll(v-if="userDialog.ref.$isProbableTroll" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Almost Nuisance
|
el-tag.x-tag-troll(v-if="userDialog.ref.$isProbableTroll" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Almost Nuisance
|
||||||
el-tag.x-tag-vip(v-if="userDialog.ref.$isModerator" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.user.tags.vrchat_team') }}
|
el-tag.x-tag-vip(v-if="userDialog.ref.$isModerator" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.user.tags.vrchat_team') }}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ mixin friendsListTab()
|
|||||||
template(v-once #default="scope")
|
template(v-once #default="scope")
|
||||||
el-button(type="text" size="mini" @click.stop)
|
el-button(type="text" size="mini" @click.stop)
|
||||||
el-checkbox(v-model="scope.row.$selected" @change="friendsListBulkUnfriendForceUpdate++")
|
el-checkbox(v-model="scope.row.$selected" @change="friendsListBulkUnfriendForceUpdate++")
|
||||||
el-table-column(:label="$t('table.friendList.no')" width="70" prop="$friendNum" sortable="custom")
|
el-table-column(:label="$t('table.friendList.no')" width="70" prop="$friendNumber" sortable="custom")
|
||||||
el-table-column(:label="$t('table.friendList.avatar')" width="70" prop="photo")
|
el-table-column(:label="$t('table.friendList.avatar')" width="70" prop="photo")
|
||||||
template(v-once #default="scope")
|
template(v-once #default="scope")
|
||||||
el-popover(placement="right" height="500px" trigger="hover")
|
el-popover(placement="right" height="500px" trigger="hover")
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ class Database {
|
|||||||
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_feed_online_offline (id INTEGER PRIMARY KEY, created_at TEXT, user_id TEXT, display_name TEXT, type TEXT, location TEXT, world_name TEXT, time INTEGER, group_name TEXT)`
|
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_feed_online_offline (id INTEGER PRIMARY KEY, created_at TEXT, user_id TEXT, display_name TEXT, type TEXT, location TEXT, world_name TEXT, time INTEGER, group_name TEXT)`
|
||||||
);
|
);
|
||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_current (user_id TEXT PRIMARY KEY, display_name TEXT, trust_level TEXT)`
|
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_current (user_id TEXT PRIMARY KEY, display_name TEXT, trust_level TEXT, friend_number INTEGER)`
|
||||||
);
|
);
|
||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_history (id INTEGER PRIMARY KEY, created_at TEXT, type TEXT, user_id TEXT, display_name TEXT, previous_display_name TEXT, trust_level TEXT, previous_trust_level TEXT)`
|
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_friend_log_history (id INTEGER PRIMARY KEY, created_at TEXT, type TEXT, user_id TEXT, display_name TEXT, previous_display_name TEXT, trust_level TEXT, previous_trust_level TEXT, friend_number INTEGER)`
|
||||||
);
|
);
|
||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_notifications (id TEXT PRIMARY KEY, created_at TEXT, type TEXT, sender_user_id TEXT, sender_username TEXT, receiver_user_id TEXT, message TEXT, world_id TEXT, world_name TEXT, image_url TEXT, invite_message TEXT, request_message TEXT, response_message TEXT, expired INTEGER)`
|
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_notifications (id TEXT PRIMARY KEY, created_at TEXT, type TEXT, sender_user_id TEXT, sender_username TEXT, receiver_user_id TEXT, message TEXT, world_id TEXT, world_name TEXT, image_url TEXT, invite_message TEXT, request_message TEXT, response_message TEXT, expired INTEGER)`
|
||||||
@@ -326,7 +326,8 @@ class Database {
|
|||||||
var row = {
|
var row = {
|
||||||
userId: dbRow[0],
|
userId: dbRow[0],
|
||||||
displayName: dbRow[1],
|
displayName: dbRow[1],
|
||||||
trustLevel: dbRow[2]
|
trustLevel: dbRow[2],
|
||||||
|
friendNumber: dbRow[3]
|
||||||
};
|
};
|
||||||
friendLogCurrent.unshift(row);
|
friendLogCurrent.unshift(row);
|
||||||
}, `SELECT * FROM ${Database.userPrefix}_friend_log_current`);
|
}, `SELECT * FROM ${Database.userPrefix}_friend_log_current`);
|
||||||
@@ -335,11 +336,12 @@ class Database {
|
|||||||
|
|
||||||
setFriendLogCurrent(entry) {
|
setFriendLogCurrent(entry) {
|
||||||
sqliteService.executeNonQuery(
|
sqliteService.executeNonQuery(
|
||||||
`INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level) VALUES (@user_id, @display_name, @trust_level)`,
|
`INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level, friend_number) VALUES (@user_id, @display_name, @trust_level, @friend_number)`,
|
||||||
{
|
{
|
||||||
'@user_id': entry.userId,
|
'@user_id': entry.userId,
|
||||||
'@display_name': entry.displayName,
|
'@display_name': entry.displayName,
|
||||||
'@trust_level': entry.trustLevel
|
'@trust_level': entry.trustLevel,
|
||||||
|
'@friend_number': entry.friendNumber
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -359,11 +361,11 @@ class Database {
|
|||||||
field[item] = '';
|
field[item] = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlValues += `('${field.userId}', '${field.displayName}', '${field.trustLevel}'), `;
|
sqlValues += `('${field.userId}', '${field.displayName}', '${field.trustLevel}', ${line.friendNumber}), `;
|
||||||
}
|
}
|
||||||
sqlValues = sqlValues.slice(0, -2);
|
sqlValues = sqlValues.slice(0, -2);
|
||||||
sqliteService.executeNonQuery(
|
sqliteService.executeNonQuery(
|
||||||
`INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level) VALUES ${sqlValues}`
|
`INSERT OR REPLACE INTO ${Database.userPrefix}_friend_log_current (user_id, display_name, trust_level, friend_number) VALUES ${sqlValues}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,7 +386,8 @@ class Database {
|
|||||||
created_at: dbRow[1],
|
created_at: dbRow[1],
|
||||||
type: dbRow[2],
|
type: dbRow[2],
|
||||||
userId: dbRow[3],
|
userId: dbRow[3],
|
||||||
displayName: dbRow[4]
|
displayName: dbRow[4],
|
||||||
|
friendNumber: dbRow[8]
|
||||||
};
|
};
|
||||||
if (row.type === 'DisplayName') {
|
if (row.type === 'DisplayName') {
|
||||||
row.previousDisplayName = dbRow[5];
|
row.previousDisplayName = dbRow[5];
|
||||||
@@ -399,7 +402,7 @@ class Database {
|
|||||||
|
|
||||||
addFriendLogHistory(entry) {
|
addFriendLogHistory(entry) {
|
||||||
sqliteService.executeNonQuery(
|
sqliteService.executeNonQuery(
|
||||||
`INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level) VALUES (@created_at, @type, @user_id, @display_name, @previous_display_name, @trust_level, @previous_trust_level)`,
|
`INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level, friend_number) VALUES (@created_at, @type, @user_id, @display_name, @previous_display_name, @trust_level, @previous_trust_level, @friend_number)`,
|
||||||
{
|
{
|
||||||
'@created_at': entry.created_at,
|
'@created_at': entry.created_at,
|
||||||
'@type': entry.type,
|
'@type': entry.type,
|
||||||
@@ -407,7 +410,8 @@ class Database {
|
|||||||
'@display_name': entry.displayName,
|
'@display_name': entry.displayName,
|
||||||
'@previous_display_name': entry.previousDisplayName,
|
'@previous_display_name': entry.previousDisplayName,
|
||||||
'@trust_level': entry.trustLevel,
|
'@trust_level': entry.trustLevel,
|
||||||
'@previous_trust_level': entry.previousTrustLevel
|
'@previous_trust_level': entry.previousTrustLevel,
|
||||||
|
'@friend_number': entry.friendNumber
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -424,7 +428,8 @@ class Database {
|
|||||||
'displayName',
|
'displayName',
|
||||||
'previousDisplayName',
|
'previousDisplayName',
|
||||||
'trustLevel',
|
'trustLevel',
|
||||||
'previousTrustLevel'
|
'previousTrustLevel',
|
||||||
|
'friendNumber'
|
||||||
];
|
];
|
||||||
for (var i = 0; i < inputData.length; ++i) {
|
for (var i = 0; i < inputData.length; ++i) {
|
||||||
var line = inputData[i];
|
var line = inputData[i];
|
||||||
@@ -449,7 +454,7 @@ class Database {
|
|||||||
// sqlValues `('${line.created_at}', '${line.type}', '${line.userId}', '${line.displayName}', '${line.previousDisplayName}', '${line.trustLevel}', '${line.previousTrustLevel}'), `
|
// sqlValues `('${line.created_at}', '${line.type}', '${line.userId}', '${line.displayName}', '${line.previousDisplayName}', '${line.trustLevel}', '${line.previousTrustLevel}'), `
|
||||||
}
|
}
|
||||||
sqliteService.executeNonQuery(
|
sqliteService.executeNonQuery(
|
||||||
`INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level) VALUES ${sqlValues}`
|
`INSERT OR IGNORE INTO ${Database.userPrefix}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level, friend_number) VALUES ${sqlValues}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2596,6 +2601,36 @@ class Database {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async upgradeDatabaseVersion() {
|
||||||
|
// var version = 0;
|
||||||
|
// await sqliteService.execute((dbRow) => {
|
||||||
|
// version = dbRow[0];
|
||||||
|
// }, 'PRAGMA user_version');
|
||||||
|
// if (version === 0) {
|
||||||
|
await this.updateTableForGroupNames();
|
||||||
|
await this.addFriendLogFriendNumber();
|
||||||
|
// }
|
||||||
|
// await sqliteService.executeNonQuery('PRAGMA user_version = 1');
|
||||||
|
}
|
||||||
|
|
||||||
|
async addFriendLogFriendNumber() {
|
||||||
|
var tables = [];
|
||||||
|
await sqliteService.execute((dbRow) => {
|
||||||
|
tables.push(dbRow[0]);
|
||||||
|
}, `SELECT name FROM sqlite_schema WHERE type='table' AND name LIKE '%_friend_log_current' OR name LIKE '%_friend_log_history'`);
|
||||||
|
for (var tableName of tables) {
|
||||||
|
try {
|
||||||
|
await sqliteService.executeNonQuery(
|
||||||
|
`ALTER TABLE ${tableName} ADD friend_number INTEGER DEFAULT 0`
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.indexOf('duplicate column name') === -1) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async updateTableForGroupNames() {
|
async updateTableForGroupNames() {
|
||||||
var tables = [];
|
var tables = [];
|
||||||
await sqliteService.execute((dbRow) => {
|
await sqliteService.execute((dbRow) => {
|
||||||
@@ -2604,28 +2639,22 @@ class Database {
|
|||||||
for (var tableName of tables) {
|
for (var tableName of tables) {
|
||||||
try {
|
try {
|
||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`SELECT group_name FROM ${tableName} LIMIT 1`
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.indexOf('no such column') === -1) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
sqliteService.executeNonQuery(
|
|
||||||
`ALTER TABLE ${tableName} ADD group_name TEXT DEFAULT ''`
|
`ALTER TABLE ${tableName} ADD group_name TEXT DEFAULT ''`
|
||||||
);
|
);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.indexOf('duplicate column name') === -1) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fix gamelog_location column typo
|
// Fix gamelog_location column typo
|
||||||
try {
|
try {
|
||||||
await sqliteService.executeNonQuery(
|
|
||||||
`SELECT groupName FROM gamelog_location LIMIT 1`
|
|
||||||
);
|
|
||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`ALTER TABLE gamelog_location DROP COLUMN groupName`
|
`ALTER TABLE gamelog_location DROP COLUMN groupName`
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.indexOf('no such column') === -1) {
|
if (e.indexOf('no such column') === -1) {
|
||||||
throw e;
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user