mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-20 23:33:50 +02:00
597 lines
24 KiB
JavaScript
597 lines
24 KiB
JavaScript
import * as workerTimers from 'worker-timers';
|
|
import configRepository from '../repository/config.js';
|
|
import { baseClass, $app, API, $t, $utils } from './baseClass.js';
|
|
|
|
export default class extends baseClass {
|
|
constructor(_app, _API, _t) {
|
|
super(_app, _API, _t);
|
|
}
|
|
|
|
_data = {
|
|
sharedFeed: {
|
|
gameLog: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
feedTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
notificationTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
friendLogTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
moderationAgainstTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
pendingUpdate: false
|
|
},
|
|
updateSharedFeedTimer: null,
|
|
updateSharedFeedPending: false,
|
|
updateSharedFeedPendingForceUpdate: false
|
|
};
|
|
|
|
_methods = {
|
|
updateSharedFeed(forceUpdate) {
|
|
if (!this.friendLogInitStatus) {
|
|
return;
|
|
}
|
|
if (this.updateSharedFeedTimer) {
|
|
if (forceUpdate) {
|
|
this.updateSharedFeedPendingForceUpdate = true;
|
|
}
|
|
this.updateSharedFeedPending = true;
|
|
} else {
|
|
this.updateSharedExecute(forceUpdate);
|
|
this.updateSharedFeedTimer = setTimeout(() => {
|
|
if (this.updateSharedFeedPending) {
|
|
this.updateSharedExecute(
|
|
this.updateSharedFeedPendingForceUpdate
|
|
);
|
|
}
|
|
this.updateSharedFeedTimer = null;
|
|
}, 150);
|
|
}
|
|
},
|
|
|
|
updateSharedExecute(forceUpdate) {
|
|
try {
|
|
this.updateSharedFeedDebounce(forceUpdate);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
this.updateSharedFeedTimer = null;
|
|
this.updateSharedFeedPending = false;
|
|
this.updateSharedFeedPendingForceUpdate = false;
|
|
},
|
|
|
|
updateSharedFeedDebounce(forceUpdate) {
|
|
this.updateSharedFeedGameLog(forceUpdate);
|
|
this.updateSharedFeedFeedTable(forceUpdate);
|
|
this.updateSharedFeedNotificationTable(forceUpdate);
|
|
this.updateSharedFeedFriendLogTable(forceUpdate);
|
|
this.updateSharedFeedModerationAgainstTable(forceUpdate);
|
|
var feeds = this.sharedFeed;
|
|
if (!feeds.pendingUpdate) {
|
|
return;
|
|
}
|
|
var wristFeed = [];
|
|
wristFeed = wristFeed.concat(
|
|
feeds.gameLog.wrist,
|
|
feeds.feedTable.wrist,
|
|
feeds.notificationTable.wrist,
|
|
feeds.friendLogTable.wrist,
|
|
feeds.moderationAgainstTable.wrist
|
|
);
|
|
// OnPlayerJoining/Traveling
|
|
API.currentTravelers.forEach((ref) => {
|
|
var isFavorite = this.localFavoriteFriends.has(ref.id);
|
|
if (
|
|
(this.sharedFeedFilters.wrist.OnPlayerJoining ===
|
|
'Friends' ||
|
|
(this.sharedFeedFilters.wrist.OnPlayerJoining ===
|
|
'VIP' &&
|
|
isFavorite)) &&
|
|
!$app.lastLocation.playerList.has(ref.id)
|
|
) {
|
|
if (ref.$location.tag === $app.lastLocation.location) {
|
|
var feedEntry = {
|
|
...ref,
|
|
isFavorite,
|
|
isFriend: true,
|
|
type: 'OnPlayerJoining'
|
|
};
|
|
wristFeed.unshift(feedEntry);
|
|
} else {
|
|
var worldRef = API.cachedWorlds.get(
|
|
ref.$location.worldId
|
|
);
|
|
var groupName = '';
|
|
if (ref.$location.groupId) {
|
|
var groupRef = API.cachedGroups.get(
|
|
ref.$location.groupId
|
|
);
|
|
if (typeof groupRef !== 'undefined') {
|
|
groupName = groupRef.name;
|
|
} else {
|
|
// no group cache, fetch group and try again
|
|
API.getGroup({
|
|
groupId: ref.$location.groupId
|
|
})
|
|
.then((args) => {
|
|
workerTimers.setTimeout(() => {
|
|
// delay to allow for group cache to update
|
|
$app.sharedFeed.pendingUpdate = true;
|
|
$app.updateSharedFeed(false);
|
|
}, 100);
|
|
return args;
|
|
})
|
|
.catch((err) => {
|
|
console.error(err);
|
|
});
|
|
}
|
|
}
|
|
if (typeof worldRef !== 'undefined') {
|
|
var feedEntry = {
|
|
created_at: ref.created_at,
|
|
type: 'GPS',
|
|
userId: ref.id,
|
|
displayName: ref.displayName,
|
|
location: ref.$location.tag,
|
|
worldName: worldRef.name,
|
|
groupName,
|
|
previousLocation: '',
|
|
isFavorite,
|
|
time: 0,
|
|
isFriend: true,
|
|
isTraveling: true
|
|
};
|
|
wristFeed.unshift(feedEntry);
|
|
} else {
|
|
// no world cache, fetch world and try again
|
|
API.getWorld({
|
|
worldId: ref.$location.worldId
|
|
})
|
|
.then((args) => {
|
|
workerTimers.setTimeout(() => {
|
|
// delay to allow for world cache to update
|
|
$app.sharedFeed.pendingUpdate = true;
|
|
$app.updateSharedFeed(false);
|
|
}, 100);
|
|
return args;
|
|
})
|
|
.catch((err) => {
|
|
console.error(err);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
wristFeed.sort(function (a, b) {
|
|
if (a.created_at < b.created_at) {
|
|
return 1;
|
|
}
|
|
if (a.created_at > b.created_at) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
});
|
|
wristFeed.splice(16);
|
|
AppApi.ExecuteVrFeedFunction(
|
|
'wristFeedUpdate',
|
|
JSON.stringify(wristFeed)
|
|
);
|
|
this.applyUserDialogLocation();
|
|
this.applyWorldDialogInstances();
|
|
this.applyGroupDialogInstances();
|
|
feeds.pendingUpdate = false;
|
|
},
|
|
|
|
updateSharedFeedGameLog(forceUpdate) {
|
|
// Location, OnPlayerJoined, OnPlayerLeft
|
|
var sessionTable = this.gameLogSessionTable;
|
|
var i = sessionTable.length;
|
|
if (i > 0) {
|
|
if (
|
|
sessionTable[i - 1].created_at ===
|
|
this.sharedFeed.gameLog.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
this.sharedFeed.gameLog.lastEntryDate =
|
|
sessionTable[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
var bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
var wristArr = [];
|
|
var w = 0;
|
|
var wristFilter = this.sharedFeedFilters.wrist;
|
|
var currentUserLeaveTime = 0;
|
|
var locationJoinTime = 0;
|
|
for (var i = sessionTable.length - 1; i > -1; i--) {
|
|
var ctx = sessionTable[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.type === 'Notification') {
|
|
continue;
|
|
}
|
|
// on Location change remove OnPlayerLeft
|
|
if (ctx.type === 'LocationDestination') {
|
|
currentUserLeaveTime = Date.parse(ctx.created_at);
|
|
var currentUserLeaveTimeOffset =
|
|
currentUserLeaveTime + 5 * 1000;
|
|
for (var k = w - 1; k > -1; k--) {
|
|
var feedItem = wristArr[k];
|
|
if (
|
|
(feedItem.type === 'OnPlayerLeft' ||
|
|
feedItem.type === 'BlockedOnPlayerLeft' ||
|
|
feedItem.type === 'MutedOnPlayerLeft') &&
|
|
Date.parse(feedItem.created_at) >=
|
|
currentUserLeaveTime &&
|
|
Date.parse(feedItem.created_at) <=
|
|
currentUserLeaveTimeOffset
|
|
) {
|
|
wristArr.splice(k, 1);
|
|
w--;
|
|
}
|
|
}
|
|
}
|
|
// on Location change remove OnPlayerJoined
|
|
if (ctx.type === 'Location') {
|
|
locationJoinTime = Date.parse(ctx.created_at);
|
|
var locationJoinTimeOffset = locationJoinTime + 20 * 1000;
|
|
for (var k = w - 1; k > -1; k--) {
|
|
var feedItem = wristArr[k];
|
|
if (
|
|
(feedItem.type === 'OnPlayerJoined' ||
|
|
feedItem.type === 'BlockedOnPlayerJoined' ||
|
|
feedItem.type === 'MutedOnPlayerJoined') &&
|
|
Date.parse(feedItem.created_at) >=
|
|
locationJoinTime &&
|
|
Date.parse(feedItem.created_at) <=
|
|
locationJoinTimeOffset
|
|
) {
|
|
wristArr.splice(k, 1);
|
|
w--;
|
|
}
|
|
}
|
|
}
|
|
// remove current user
|
|
if (
|
|
(ctx.type === 'OnPlayerJoined' ||
|
|
ctx.type === 'OnPlayerLeft' ||
|
|
ctx.type === 'PortalSpawn') &&
|
|
ctx.displayName === API.currentUser.displayName
|
|
) {
|
|
continue;
|
|
}
|
|
var isFriend = false;
|
|
var isFavorite = false;
|
|
if (ctx.userId) {
|
|
isFriend = this.friends.has(ctx.userId);
|
|
isFavorite = this.localFavoriteFriends.has(ctx.userId);
|
|
} else if (ctx.displayName) {
|
|
for (var ref of API.cachedUsers.values()) {
|
|
if (ref.displayName === ctx.displayName) {
|
|
isFriend = this.friends.has(ref.id);
|
|
isFavorite = this.localFavoriteFriends.has(ref.id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// add tag colour
|
|
var tagColour = '';
|
|
if (ctx.userId) {
|
|
var tagRef = this.customUserTags.get(ctx.userId);
|
|
if (typeof tagRef !== 'undefined') {
|
|
tagColour = tagRef.colour;
|
|
}
|
|
}
|
|
// BlockedOnPlayerJoined, BlockedOnPlayerLeft, MutedOnPlayerJoined, MutedOnPlayerLeft
|
|
if (
|
|
ctx.type === 'OnPlayerJoined' ||
|
|
ctx.type === 'OnPlayerLeft'
|
|
) {
|
|
for (var ref of API.cachedPlayerModerations.values()) {
|
|
if (
|
|
ref.targetDisplayName !== ctx.displayName &&
|
|
ref.sourceUserId !== ctx.userId
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
if (ref.type === 'block') {
|
|
var type = `Blocked${ctx.type}`;
|
|
} else if (ref.type === 'mute') {
|
|
var type = `Muted${ctx.type}`;
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
var entry = {
|
|
created_at: ctx.created_at,
|
|
type,
|
|
displayName: ref.targetDisplayName,
|
|
userId: ref.targetUserId,
|
|
isFriend,
|
|
isFavorite
|
|
};
|
|
if (
|
|
wristFilter[type] &&
|
|
(wristFilter[type] === 'Everyone' ||
|
|
(wristFilter[type] === 'Friends' && isFriend) ||
|
|
(wristFilter[type] === 'VIP' && isFavorite))
|
|
) {
|
|
wristArr.unshift(entry);
|
|
}
|
|
this.queueGameLogNoty(entry);
|
|
}
|
|
}
|
|
// when too many user joins happen at once when switching instances
|
|
// the "w" counter maxes out and wont add any more entries
|
|
// until the onJoins are cleared by "Location"
|
|
// e.g. if a "VideoPlay" occurs between "OnPlayerJoined" and "Location" it wont be added
|
|
if (
|
|
w < 50 &&
|
|
wristFilter[ctx.type] &&
|
|
(wristFilter[ctx.type] === 'On' ||
|
|
wristFilter[ctx.type] === 'Everyone' ||
|
|
(wristFilter[ctx.type] === 'Friends' && isFriend) ||
|
|
(wristFilter[ctx.type] === 'VIP' && isFavorite))
|
|
) {
|
|
wristArr.push({
|
|
...ctx,
|
|
tagColour,
|
|
isFriend,
|
|
isFavorite
|
|
});
|
|
++w;
|
|
}
|
|
}
|
|
this.sharedFeed.gameLog.wrist = wristArr;
|
|
this.sharedFeed.pendingUpdate = true;
|
|
},
|
|
|
|
updateSharedFeedFeedTable(forceUpdate) {
|
|
// GPS, Online, Offline, Status, Avatar
|
|
var feedSession = this.feedSessionTable;
|
|
var i = feedSession.length;
|
|
if (i > 0) {
|
|
if (
|
|
feedSession[i - 1].created_at ===
|
|
this.sharedFeed.feedTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
this.sharedFeed.feedTable.lastEntryDate =
|
|
feedSession[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
var bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
var wristArr = [];
|
|
var w = 0;
|
|
var wristFilter = this.sharedFeedFilters.wrist;
|
|
for (var i = feedSession.length - 1; i > -1; i--) {
|
|
var ctx = feedSession[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.type === 'Avatar') {
|
|
continue;
|
|
}
|
|
// hide private worlds from feed
|
|
if (
|
|
this.hidePrivateFromFeed &&
|
|
ctx.type === 'GPS' &&
|
|
ctx.location === 'private'
|
|
) {
|
|
continue;
|
|
}
|
|
var isFriend = this.friends.has(ctx.userId);
|
|
var isFavorite = this.localFavoriteFriends.has(ctx.userId);
|
|
if (
|
|
w < 20 &&
|
|
wristFilter[ctx.type] &&
|
|
(wristFilter[ctx.type] === 'Friends' ||
|
|
(wristFilter[ctx.type] === 'VIP' && isFavorite))
|
|
) {
|
|
wristArr.push({
|
|
...ctx,
|
|
isFriend,
|
|
isFavorite
|
|
});
|
|
++w;
|
|
}
|
|
}
|
|
this.sharedFeed.feedTable.wrist = wristArr;
|
|
this.sharedFeed.pendingUpdate = true;
|
|
},
|
|
|
|
updateSharedFeedNotificationTable(forceUpdate) {
|
|
// invite, requestInvite, requestInviteResponse, inviteResponse, friendRequest
|
|
var notificationTable = this.notificationTable;
|
|
var i = notificationTable.length;
|
|
if (i > 0) {
|
|
if (
|
|
notificationTable[i - 1].created_at ===
|
|
this.sharedFeed.notificationTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
this.sharedFeed.notificationTable.lastEntryDate =
|
|
notificationTable[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
var bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
var wristArr = [];
|
|
var w = 0;
|
|
var wristFilter = this.sharedFeedFilters.wrist;
|
|
for (var i = notificationTable.length - 1; i > -1; i--) {
|
|
var ctx = notificationTable[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.senderUserId === API.currentUser.id) {
|
|
continue;
|
|
}
|
|
var isFriend = this.friends.has(ctx.senderUserId);
|
|
var isFavorite = this.localFavoriteFriends.has(
|
|
ctx.senderUserId
|
|
);
|
|
if (
|
|
w < 20 &&
|
|
wristFilter[ctx.type] &&
|
|
(wristFilter[ctx.type] === 'On' ||
|
|
wristFilter[ctx.type] === 'Friends' ||
|
|
(wristFilter[ctx.type] === 'VIP' && isFavorite))
|
|
) {
|
|
wristArr.push({
|
|
...ctx,
|
|
isFriend,
|
|
isFavorite
|
|
});
|
|
++w;
|
|
}
|
|
}
|
|
this.sharedFeed.notificationTable.wrist = wristArr;
|
|
this.sharedFeed.pendingUpdate = true;
|
|
},
|
|
|
|
updateSharedFeedFriendLogTable(forceUpdate) {
|
|
// TrustLevel, Friend, FriendRequest, Unfriend, DisplayName
|
|
var friendLog = this.friendLogTable;
|
|
var i = friendLog.length;
|
|
if (i > 0) {
|
|
if (
|
|
friendLog[i - 1].created_at ===
|
|
this.sharedFeed.friendLogTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
this.sharedFeed.friendLogTable.lastEntryDate =
|
|
friendLog[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
var bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
var wristArr = [];
|
|
var w = 0;
|
|
var wristFilter = this.sharedFeedFilters.wrist;
|
|
for (var i = friendLog.length - 1; i > -1; i--) {
|
|
var ctx = friendLog[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.type === 'FriendRequest') {
|
|
continue;
|
|
}
|
|
var isFriend = this.friends.has(ctx.userId);
|
|
var isFavorite = this.localFavoriteFriends.has(ctx.userId);
|
|
if (
|
|
w < 20 &&
|
|
wristFilter[ctx.type] &&
|
|
(wristFilter[ctx.type] === 'On' ||
|
|
wristFilter[ctx.type] === 'Friends' ||
|
|
(wristFilter[ctx.type] === 'VIP' && isFavorite))
|
|
) {
|
|
wristArr.push({
|
|
...ctx,
|
|
isFriend,
|
|
isFavorite
|
|
});
|
|
++w;
|
|
}
|
|
}
|
|
this.sharedFeed.friendLogTable.wrist = wristArr;
|
|
this.sharedFeed.pendingUpdate = true;
|
|
},
|
|
|
|
updateSharedFeedModerationAgainstTable(forceUpdate) {
|
|
// Unblocked, Blocked, Muted, Unmuted
|
|
var moderationAgainst = this.moderationAgainstTable;
|
|
var i = moderationAgainst.length;
|
|
if (i > 0) {
|
|
if (
|
|
moderationAgainst[i - 1].created_at ===
|
|
this.sharedFeed.moderationAgainstTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
this.sharedFeed.moderationAgainstTable.lastEntryDate =
|
|
moderationAgainst[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
var bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
var wristArr = [];
|
|
var w = 0;
|
|
var wristFilter = this.sharedFeedFilters.wrist;
|
|
for (var i = moderationAgainst.length - 1; i > -1; i--) {
|
|
var ctx = moderationAgainst[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
var isFriend = this.friends.has(ctx.userId);
|
|
var isFavorite = this.localFavoriteFriends.has(ctx.userId);
|
|
// add tag colour
|
|
var tagColour = '';
|
|
var tagRef = this.customUserTags.get(ctx.userId);
|
|
if (typeof tagRef !== 'undefined') {
|
|
tagColour = tagRef.colour;
|
|
}
|
|
if (
|
|
w < 20 &&
|
|
wristFilter[ctx.type] &&
|
|
wristFilter[ctx.type] === 'On'
|
|
) {
|
|
wristArr.push({
|
|
...ctx,
|
|
isFriend,
|
|
isFavorite,
|
|
tagColour
|
|
});
|
|
++w;
|
|
}
|
|
}
|
|
this.sharedFeed.moderationAgainstTable.wrist = wristArr;
|
|
this.sharedFeed.pendingUpdate = true;
|
|
},
|
|
|
|
saveSharedFeedFilters() {
|
|
configRepository.setString(
|
|
'sharedFeedFilters',
|
|
JSON.stringify(this.sharedFeedFilters)
|
|
);
|
|
this.updateSharedFeed(true);
|
|
},
|
|
|
|
async resetNotyFeedFilters() {
|
|
this.sharedFeedFilters.noty = {
|
|
...this.sharedFeedFiltersDefaults.noty
|
|
};
|
|
this.saveSharedFeedFilters();
|
|
},
|
|
|
|
async resetWristFeedFilters() {
|
|
this.sharedFeedFilters.wrist = {
|
|
...this.sharedFeedFiltersDefaults.wrist
|
|
};
|
|
this.saveSharedFeedFilters();
|
|
}
|
|
};
|
|
}
|