diff --git a/html/src/app.js b/html/src/app.js
index 4253ffa9..eb09ca28 100644
--- a/html/src/app.js
+++ b/html/src/app.js
@@ -1755,21 +1755,6 @@ speechSynthesis.getVoices();
// API: Friend
- API.friends200 = new Set();
- API.friends404 = new Map();
- API.isFriendsLoading = false;
-
- API.$on('LOGIN', function () {
- this.friends200.clear();
- this.friends404.clear();
- this.isFriendsLoading = false;
- });
-
- API.$on('USER', function (args) {
- this.friends200.add(args.ref.id);
- this.friends404.delete(args.ref.id);
- });
-
API.$on('FRIEND:LIST', function (args) {
for (var json of args.json) {
this.$emit('USER', {
@@ -1781,65 +1766,45 @@ speechSynthesis.getVoices();
}
});
- API.isAllFriendsRetrived = function (flag) {
- if (flag) {
- for (var id of this.currentUser.friends) {
- if (this.friends200.has(id) === false) {
- var n = this.friends404.get(id) || 0;
- if (n < 2) {
- this.friends404.set(id, n + 1);
- }
- }
- }
- } else {
- for (var id of this.currentUser.friends) {
- if (this.friends200.has(id) === false ||
- this.friends404.get(id) < 2) {
- return false;
- }
- }
- }
- return true;
+ API.refreshFriends = async function () {
+ var onlineFriends = await this.refreshOnlineFriends();
+ var offlineFriends = await this.refreshOfflineFriends();
+ return onlineFriends.concat(offlineFriends);
};
- API.refreshFriends = function () {
+ API.refreshOnlineFriends = async function () {
+ var friends = [];
var params = {
n: 50,
offset: 0,
offline: false
};
- var N = this.currentUser.onlineFriends.length;
- if (N === 0) {
- N = this.currentUser.friends.length;
- if (N === 0 ||
- this.isAllFriendsRetrived(false)) {
- return;
- }
- params.offline = true;
+ var N = this.currentUser.onlineFriends.length + this.currentUser.activeFriends.length;
+ var count = Math.trunc(N / 50);
+ for (var i = count; i > -1; i--) {
+ var args = await this.getFriends(params);
+ friends = friends.concat(args.json);
+ params.offset += 50;
}
- if (this.isFriendsLoading) {
- return;
+ return friends;
+ };
+
+ API.refreshOfflineFriends = async function () {
+ var friends = [];
+ var params = {
+ n: 50,
+ offset: 0,
+ offline: true
+ };
+ var onlineCount = this.currentUser.onlineFriends.length + this.currentUser.activeFriends.length;
+ var N = this.currentUser.friends.length - onlineCount;
+ var count = Math.trunc(N / 50);
+ for (var i = count; i > -1; i--) {
+ var args = await this.getFriends(params);
+ friends = friends.concat(args.json);
+ params.offset += 50;
}
- this.isFriendsLoading = true;
- this.bulk({
- fn: 'getFriends',
- N,
- params,
- done(ok, options) {
- if (this.isAllFriendsRetrived(params.offline)) {
- this.isFriendsLoading = false;
- return;
- }
- var { length } = this.currentUser.friends;
- options.N = length - params.offset;
- if (options.N <= 0) {
- options.N = length;
- }
- params.offset = 0;
- params.offline = true;
- this.bulk(options);
- }
- });
+ return friends;
};
/*
@@ -5284,18 +5249,20 @@ speechSynthesis.getVoices();
}
};
- $app.methods.migrateMemos = function () {
+ $app.methods.migrateMemos = async function () {
var json = JSON.parse(VRCXStorage.GetAll());
+ database.begin();
for (var line in json) {
if (line.substring(0, 8) === 'memo_usr') {
var userId = line.substring(5);
var memo = json[line];
if (memo) {
- this.saveMemo(userId, memo);
+ await this.saveMemo(userId, memo);
VRCXStorage.Remove(`memo_${userId}`);
}
}
}
+ database.commit();
};
$app.methods.loadMemo = async function (userId) {
@@ -6134,17 +6101,21 @@ speechSynthesis.getVoices();
}
API.$on('LOGIN', async function (args) {
+ $app.friendLogInitStatus = false;
await database.init(args.json.id);
$app.feedTable.data = await database.getFeedDatabase();
$app.sweepFeed();
- //remove old data from json file and migrate them to SQLite
- VRCXStorage.Remove(`${args.json.id}_feedTable`);
- $app.migrateMemos();
- if (VRCXStorage.Get(`${args.json.id}_friendLogUpdatedAt`)) {
- $app.migrateFriendLog(args.json.id);
+ if (configRepository.getBool(`friendLogInit_${args.json.id}`)) {
+ $app.getFriendLog();
} else {
$app.initFriendLog();
}
+ //remove old data from json file and migrate them to SQLite
+ if (VRCXStorage.Get(`${args.json.id}_friendLogUpdatedAt`)) {
+ VRCXStorage.Remove(`${args.json.id}_feedTable`);
+ $app.migrateMemos();
+ $app.migrateFriendLog(args.json.id);
+ }
});
API.$on('USER:UPDATE', async function (args) {
@@ -7116,9 +7087,36 @@ speechSynthesis.getVoices();
$app.data.friendLogInitStatus = false;
+ $app.methods.initFriendLog = async function () {
+ if (this.friendLogInitStatus) {
+ return;
+ }
+ if (configRepository.getBool(`friendLogInit_${API.currentUser.id}`)) {
+ this.friendLogInitStatus = true;
+ return;
+ }
+ var sqlValues = [];
+ var friends = await API.refreshFriends();
+ for (var friend of friends) {
+ var ref = API.applyUser(friend);
+ var row = {
+ userId: ref.id,
+ displayName: ref.displayName,
+ trustLevel: ref.$trustLevel
+ };
+ this.friendLog.set(friend.id, row);
+ sqlValues.unshift(row);
+ }
+ database.setFriendLogCurrentArray(sqlValues);
+ configRepository.setBool(`friendLogInit_${API.currentUser.id}`, true);
+ this.friendLogInitStatus = true;
+ };
+
$app.methods.migrateFriendLog = function (userId) {
+ VRCXStorage.Remove(`${userId}_friendLogUpdatedAt`);
this.friendLog = new Map();
var oldFriendLog = VRCXStorage.GetObject(`${userId}_friendLog`);
+ var friendLogCurrentValues = [];
for (var i in oldFriendLog) {
var friend = oldFriendLog[i];
var row = {
@@ -7127,19 +7125,18 @@ speechSynthesis.getVoices();
trustLevel: friend.trustLevel
};
this.friendLog.set(friend.id, row);
- database.setFriendLogCurrent(row);
+ friendLogCurrentValues.unshift(row);
}
+ database.setFriendLogCurrentArray(friendLogCurrentValues);
VRCXStorage.Remove(`${userId}_friendLog`);
this.friendLogTable.data = VRCXStorage.GetArray(`${userId}_friendLogTable`);
- for (var line of this.friendLogTable.data) {
- database.addFriendLogHistory(line);
- }
+ database.addFriendLogHistoryArray(this.friendLogTable.data);
VRCXStorage.Remove(`${userId}_friendLogTable`);
- VRCXStorage.Remove(`${userId}_friendLogUpdatedAt`);
+ configRepository.setBool(`friendLogInit_${API.currentUser.id}`, true);
this.friendLogInitStatus = true;
};
- $app.methods.initFriendLog = async function () {
+ $app.methods.getFriendLog = async function () {
this.friendLog = new Map();
var friendLogCurrentArray = await database.getFriendLogCurrent();
for (var friend of friendLogCurrentArray) {
@@ -7239,14 +7236,14 @@ speechSynthesis.getVoices();
};
this.friendLogTable.data.push(friendLogHistory);
database.addFriendLogHistory(friendLogHistory);
- var friendLogCurrent = {
- userId: ref.id,
- displayName: ref.displayName,
- trustLevel: ref.$trustLevel
- };
- this.friendLog.set(ref.id, friendLogCurrent);
- database.setFriendLogCurrent(friendLogCurrent);
}
+ var friendLogCurrent = {
+ userId: ref.id,
+ displayName: ref.displayName,
+ trustLevel: ref.$trustLevel
+ };
+ this.friendLog.set(ref.id, friendLogCurrent);
+ database.setFriendLogCurrent(friendLogCurrent);
ctx.displayName = ref.displayName;
this.notifyMenu('friendLog');
}
diff --git a/html/src/repository/database.js b/html/src/repository/database.js
index 46ec676d..6194dcd3 100644
--- a/html/src/repository/database.js
+++ b/html/src/repository/database.js
@@ -103,6 +103,14 @@ class Database {
return feedDatabase;
}
+ begin() {
+ sqliteService.executeNonQuery('BEGIN');
+ }
+
+ commit() {
+ sqliteService.executeNonQuery('COMMIT');
+ }
+
async getMemo(userId) {
var row = {};
await sqliteService.execute((dbRow, userId) => {
@@ -159,6 +167,25 @@ class Database {
);
}
+ setFriendLogCurrentArray(inputData) {
+ var sqlValues = '';
+ var items = ['userId', 'displayName', 'trustLevel'];
+ for (var line of inputData) {
+ for (var item of items) {
+ if (typeof line[item] !== 'undefined') {
+ line[item] = line[item].replace(/'/g, "\''");
+ } else {
+ line[item] = '';
+ }
+ }
+ sqlValues += `('${line.userId}', '${line.displayName}', '${line.trustLevel}'), `;
+ }
+ sqlValues = sqlValues.slice(0, -2);
+ sqliteService.executeNonQuery(
+ `INSERT OR REPLACE INTO ${Database.userId}_friend_log_current (user_id, display_name, trust_level) VALUES ${sqlValues}`
+ );
+ }
+
deleteFriendLogCurrent(userId) {
sqliteService.executeNonQuery(
`DELETE FROM ${Database.userId}_friend_log_current WHERE user_id = @user_id`,
@@ -204,6 +231,36 @@ class Database {
);
}
+ addFriendLogHistoryArray(inputData) {
+ var sqlValues = '';
+ var items = ['created_at', 'type', 'userId', 'displayName', 'previousDisplayName', 'trustLevel', 'previousTrustLevel'];
+ for (var i = 0; i < inputData.length; ++i) {
+ var line = inputData[i];
+ sqlValues += '(';
+ for (var k = 0; k < items.length; ++k) {
+ var item = items[k];
+ var field = '';
+ if (typeof line[item] !== 'undefined') {
+ field = `'${line[item].replace(/'/g, "\''")}'`;
+ } else {
+ field = null;
+ }
+ sqlValues += field;
+ if (k < items.length - 1) {
+ sqlValues += ', ';
+ }
+ }
+ sqlValues += ')';
+ if (i < inputData.length - 1) {
+ sqlValues += ', ';
+ }
+ //sqlValues `('${line.created_at}', '${line.type}', '${line.userId}', '${line.displayName}', '${line.previousDisplayName}', '${line.trustLevel}', '${line.previousTrustLevel}'), `
+ }
+ sqliteService.executeNonQuery(
+ `INSERT OR IGNORE INTO ${Database.userId}_friend_log_history (created_at, type, user_id, display_name, previous_display_name, trust_level, previous_trust_level) VALUES ${sqlValues}`
+ );
+ }
+
deleteFriendLogHistory(rowId) {
sqliteService.executeNonQuery(
`DELETE FROM ${Database.userId}_friend_log_history WHERE id = @row_id`,
diff --git a/html/src/vr.pug b/html/src/vr.pug
index 7e3f42bd..f5a72ac7 100644
--- a/html/src/vr.pug
+++ b/html/src/vr.pug
@@ -62,7 +62,7 @@ html
.detail
span.extra
span.time {{ feed.created_at | formatDate('HH:MI') }}
- | 📨 #[span.name(v-text="feed.senderUsername")] #[location(:location="feed.details.worldId")] #[span(v-text="feed.details.inviteMessage")]
+ | 📨 #[span.name(v-text="feed.senderUsername")] #[location(:location="feed.details.worldId" :hint="feed.details.worldName")] #[span(v-text="feed.details.inviteMessage")]
div(v-else-if="feed.type === 'requestInvite'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
.detail
span.extra
@@ -184,7 +184,7 @@ html
.detail
span.extra
span.time {{ feed.created_at | formatDate('HH:MI') }}
- | #[span.name(v-text="feed.senderUsername")] has invited you to #[location(:location="feed.details.worldId")] #[span(v-text="feed.details.inviteMessage")]
+ | #[span.name(v-text="feed.senderUsername")] has invited you to #[location(:location="feed.details.worldId" :hint="feed.details.worldName")] #[span(v-text="feed.details.inviteMessage")]
div(v-else-if="feed.type === 'requestInvite'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
.detail
span.extra