mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-14 04:13:52 +02:00
424 lines
14 KiB
JavaScript
424 lines
14 KiB
JavaScript
import { defineStore } from 'pinia';
|
|
import { ref } from 'vue';
|
|
import { watch } from 'vue';
|
|
|
|
import {
|
|
compareByCreatedAt,
|
|
getGroupName,
|
|
getWorldName
|
|
} from '../shared/utils';
|
|
import { database } from '../service/database';
|
|
import { useFriendStore } from './friend';
|
|
import { useInstanceStore } from './instance';
|
|
import { useLocationStore } from './location';
|
|
import { useModerationStore } from './moderation';
|
|
import { useNotificationStore } from './notification';
|
|
import { useNotificationsSettingsStore } from './settings/notifications';
|
|
import { useUserStore } from './user';
|
|
import { useWristOverlaySettingsStore } from './settings/wristOverlay';
|
|
import { watchState } from '../service/watchState';
|
|
|
|
export const useSharedFeedStore = defineStore('SharedFeed', () => {
|
|
const friendStore = useFriendStore();
|
|
const notificationsSettingsStore = useNotificationsSettingsStore();
|
|
const locationStore = useLocationStore();
|
|
const userStore = useUserStore();
|
|
const wristOverlaySettingsStore = useWristOverlaySettingsStore();
|
|
const instanceStore = useInstanceStore();
|
|
const moderationStore = useModerationStore();
|
|
const notificationStore = useNotificationStore();
|
|
|
|
const onPlayerJoining = ref([]);
|
|
|
|
async function rebuildOnPlayerJoining() {
|
|
let newOnPlayerJoining = [];
|
|
for (const ref of userStore.currentTravelers.values()) {
|
|
const isFavorite = friendStore.localFavoriteFriends.has(ref.id);
|
|
if (
|
|
locationStore.lastLocation.playerList.has(ref.id) ||
|
|
(notificationsSettingsStore.sharedFeedFilters.wrist
|
|
.OnPlayerJoining === 'VIP' &&
|
|
!isFavorite)
|
|
) {
|
|
continue;
|
|
}
|
|
if (ref.$location.tag === locationStore.lastLocation.location) {
|
|
const feedEntry = {
|
|
...ref,
|
|
isFavorite,
|
|
isFriend: true,
|
|
type: 'OnPlayerJoining'
|
|
};
|
|
newOnPlayerJoining.unshift(feedEntry);
|
|
continue;
|
|
}
|
|
const worldName = await getWorldName(ref.$location.worldId);
|
|
const groupName = await getGroupName(ref.$location.groupId);
|
|
const feedEntry = {
|
|
created_at: ref.created_at,
|
|
type: 'GPS',
|
|
userId: ref.id,
|
|
displayName: ref.displayName,
|
|
location: ref.$location.tag,
|
|
worldName,
|
|
groupName,
|
|
previousLocation: '',
|
|
isFavorite,
|
|
time: 0,
|
|
isFriend: true,
|
|
isTraveling: true
|
|
};
|
|
newOnPlayerJoining.unshift(feedEntry);
|
|
}
|
|
onPlayerJoining.value = newOnPlayerJoining;
|
|
|
|
sharedFeedData.value = sharedFeedData.value.filter(
|
|
(ctx) =>
|
|
!(
|
|
ctx.type === 'OnPlayerJoining' ||
|
|
(ctx.type === 'GPS' && ctx.isTraveling)
|
|
)
|
|
);
|
|
sharedFeedData.value.unshift(...onPlayerJoining.value);
|
|
if (sharedFeedData.value.length > maxEntries) {
|
|
sharedFeedData.value.splice(maxEntries);
|
|
}
|
|
sendSharedFeed();
|
|
}
|
|
|
|
watch(
|
|
() => userStore.currentTravelers,
|
|
() => rebuildOnPlayerJoining(),
|
|
{ deep: true }
|
|
);
|
|
|
|
watch(
|
|
() => watchState.isLoggedIn,
|
|
(isLoggedIn) => {
|
|
if (isLoggedIn) {
|
|
sharedFeedData.value = [];
|
|
loadSharedFeed();
|
|
}
|
|
},
|
|
{ flush: 'sync' }
|
|
);
|
|
|
|
const sharedFeedData = ref([]);
|
|
const maxEntries = 25;
|
|
|
|
async function loadSharedFeed() {
|
|
let newFeed = [];
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
// run after fav and friendlist init
|
|
const vipList = Array.from(friendStore.localFavoriteFriends.values());
|
|
const friendList = Array.from(friendStore.friends.keys());
|
|
|
|
// Filters
|
|
const vipFilters = Object.keys(wristFilter).filter(
|
|
(key) => wristFilter[key] === 'VIP'
|
|
);
|
|
const friendsFilters = Object.keys(wristFilter).filter(
|
|
(key) => wristFilter[key] === 'Friends'
|
|
);
|
|
const everyoneFilters = Object.keys(wristFilter).filter(
|
|
(key) =>
|
|
wristFilter[key] === 'On' || wristFilter[key] === 'Everyone'
|
|
);
|
|
const everyoneAndFriendsFilters = Object.keys(wristFilter).filter(
|
|
(key) =>
|
|
wristFilter[key] === 'Friends' ||
|
|
wristFilter[key] === 'On' ||
|
|
wristFilter[key] === 'Everyone'
|
|
);
|
|
|
|
// Feed
|
|
if (vipFilters.length) {
|
|
const vipFeedRows = await database.lookupFeedDatabase(
|
|
vipFilters,
|
|
vipList,
|
|
maxEntries
|
|
);
|
|
newFeed = newFeed.concat(vipFeedRows);
|
|
}
|
|
if (everyoneAndFriendsFilters.length) {
|
|
const friendsFeedRows = await database.lookupFeedDatabase(
|
|
everyoneAndFriendsFilters,
|
|
[],
|
|
maxEntries
|
|
);
|
|
newFeed = newFeed.concat(friendsFeedRows);
|
|
}
|
|
|
|
// GameLog
|
|
if (vipFilters.length) {
|
|
const vipGameLogRows = await database.lookupGameLogDatabase(
|
|
'',
|
|
vipFilters,
|
|
vipList,
|
|
maxEntries
|
|
);
|
|
newFeed = newFeed.concat(vipGameLogRows);
|
|
}
|
|
if (friendsFilters.length) {
|
|
const friendsGameLogRows = await database.lookupGameLogDatabase(
|
|
'',
|
|
friendsFilters,
|
|
friendList,
|
|
maxEntries
|
|
);
|
|
newFeed = newFeed.concat(friendsGameLogRows);
|
|
}
|
|
if (everyoneFilters.length) {
|
|
const everyoneGameLogRows = await database.lookupGameLogDatabase(
|
|
'',
|
|
everyoneFilters,
|
|
[],
|
|
maxEntries
|
|
);
|
|
newFeed = newFeed.concat(everyoneGameLogRows);
|
|
}
|
|
|
|
// Notifications
|
|
if (vipFilters.length) {
|
|
const vipNotificationRows =
|
|
await database.lookupNotificationDatabase(
|
|
'',
|
|
vipFilters,
|
|
vipList,
|
|
maxEntries
|
|
);
|
|
newFeed = newFeed.concat(vipNotificationRows);
|
|
}
|
|
if (everyoneAndFriendsFilters.length) {
|
|
const friendsNotificationRows =
|
|
await database.lookupNotificationDatabase(
|
|
'',
|
|
everyoneAndFriendsFilters,
|
|
[],
|
|
maxEntries
|
|
);
|
|
newFeed = newFeed.concat(friendsNotificationRows);
|
|
}
|
|
|
|
// hide private worlds from feed
|
|
if (wristOverlaySettingsStore.hidePrivateFromFeed) {
|
|
newFeed = newFeed.filter(
|
|
(ctx) => !(ctx.type === 'GPS' && ctx.location === 'private')
|
|
);
|
|
}
|
|
|
|
// remove current user
|
|
newFeed = newFeed.filter(
|
|
(ctx) => ctx.userId !== userStore.currentUser.id
|
|
);
|
|
|
|
// FriendLog, Moderations Against (nope, not worth it)
|
|
|
|
newFeed.sort(compareByCreatedAt);
|
|
newFeed.splice(maxEntries);
|
|
|
|
for (const entry of newFeed) {
|
|
const userId = entry.userId || entry.senderUserId;
|
|
entry.isFriend = false;
|
|
entry.isFavorite = false;
|
|
entry.tagColour = '';
|
|
if (userId) {
|
|
entry.isFriend = friendStore.friends.has(userId);
|
|
entry.isFavorite = friendStore.localFavoriteFriends.has(userId);
|
|
entry.tagColour =
|
|
userStore.customUserTags.get(userId)?.colour ?? '';
|
|
}
|
|
// tack on instance names
|
|
const location = entry.location || entry.details?.location;
|
|
if (location) {
|
|
entry.instanceDisplayName =
|
|
await instanceStore.getInstanceName(location);
|
|
}
|
|
}
|
|
sharedFeedData.value = newFeed;
|
|
rebuildOnPlayerJoining(); // also sends updated feed
|
|
}
|
|
|
|
async function addEntry(data) {
|
|
const ctx = { ...data };
|
|
const userId = ctx.userId || ctx.senderUserId;
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
if (userId === userStore.currentUser.id) {
|
|
return;
|
|
}
|
|
if (
|
|
wristOverlaySettingsStore.hidePrivateFromFeed &&
|
|
ctx.type === 'GPS' &&
|
|
ctx.location === 'private'
|
|
) {
|
|
return;
|
|
}
|
|
if (ctx.type === 'FriendRequest' || ctx.type === 'Avatar') {
|
|
return;
|
|
}
|
|
|
|
let isFriend = false;
|
|
let isFavorite = false;
|
|
let tagColour = '';
|
|
if (userId) {
|
|
isFriend = friendStore.friends.has(userId);
|
|
isFavorite = friendStore.localFavoriteFriends.has(userId);
|
|
tagColour = userStore.customUserTags.get(userId)?.colour ?? '';
|
|
}
|
|
// tack on instance names
|
|
const location = ctx.location || ctx.details?.location;
|
|
if (location) {
|
|
ctx.instanceDisplayName =
|
|
await instanceStore.getInstanceName(location);
|
|
}
|
|
|
|
// TODO: videoPlay come through before it gets video name
|
|
|
|
// TODO: On Location change remove OnPlayerLeft & OnPlayerJoined
|
|
{
|
|
// on Location change remove OnPlayerLeft
|
|
// if (ctx.type === 'LocationDestination') {
|
|
// if (!ctxTime) {
|
|
// ctxTime = Date.parse(ctx.created_at);
|
|
// }
|
|
// currentUserLeaveTime = ctxTime;
|
|
// const currentUserLeaveTimeOffset = currentUserLeaveTime + 5 * 1000;
|
|
// for (var k = w - 1; k > -1; k--) {
|
|
// var feedItem = wristArr[k];
|
|
// const feedItemTime = Date.parse(feedItem.created_at);
|
|
// if (
|
|
// (feedItem.type === 'OnPlayerLeft' ||
|
|
// feedItem.type === 'BlockedOnPlayerLeft' ||
|
|
// feedItem.type === 'MutedOnPlayerLeft') &&
|
|
// feedItemTime >= currentUserLeaveTime &&
|
|
// feedItemTime <= currentUserLeaveTimeOffset
|
|
// ) {
|
|
// wristArr.splice(k, 1);
|
|
// w--;
|
|
// }
|
|
// }
|
|
// }
|
|
// on Location change remove OnPlayerJoined
|
|
// if (ctx.type === 'Location') {
|
|
// if (!ctxTime) {
|
|
// ctxTime = Date.parse(ctx.created_at);
|
|
// }
|
|
// locationJoinTime = ctxTime;
|
|
// const locationJoinTimeOffset = locationJoinTime + 20 * 1000;
|
|
// for (let k = w - 1; k > -1; k--) {
|
|
// let feedItem = wristArr[k];
|
|
// const feedItemTime = Date.parse(feedItem.created_at);
|
|
// if (
|
|
// (feedItem.type === 'OnPlayerJoined' ||
|
|
// feedItem.type === 'BlockedOnPlayerJoined' ||
|
|
// feedItem.type === 'MutedOnPlayerJoined') &&
|
|
// feedItemTime >= locationJoinTime &&
|
|
// feedItemTime <= locationJoinTimeOffset
|
|
// ) {
|
|
// wristArr.splice(k, 1);
|
|
// w--;
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
if (ctx.type === 'OnPlayerJoined' || ctx.type === 'OnPlayerLeft') {
|
|
moderationAgainstCheck({
|
|
...ctx,
|
|
isFavorite,
|
|
isFriend,
|
|
tagColour
|
|
});
|
|
}
|
|
|
|
if (
|
|
wristFilter[ctx.type] &&
|
|
(wristFilter[ctx.type] === 'On' ||
|
|
wristFilter[ctx.type] === 'Everyone' ||
|
|
(wristFilter[ctx.type] === 'Friends' && isFriend) ||
|
|
(wristFilter[ctx.type] === 'VIP' && isFavorite))
|
|
) {
|
|
addToSharedFeed({
|
|
...ctx,
|
|
isFavorite,
|
|
isFriend,
|
|
tagColour
|
|
});
|
|
}
|
|
}
|
|
|
|
function addToSharedFeed(ref) {
|
|
sharedFeedData.value.unshift(ref);
|
|
if (sharedFeedData.value.length > maxEntries) {
|
|
sharedFeedData.value.splice(maxEntries);
|
|
}
|
|
sendSharedFeed();
|
|
}
|
|
|
|
function moderationAgainstCheck(ctx) {
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
// BlockedOnPlayerJoined, BlockedOnPlayerLeft, MutedOnPlayerJoined, MutedOnPlayerLeft
|
|
for (const ref of moderationStore.cachedPlayerModerations.values()) {
|
|
if (ref.sourceUserId !== ctx.userId) {
|
|
continue;
|
|
}
|
|
|
|
let type = '';
|
|
if (ref.type === 'block') {
|
|
type = `Blocked${ctx.type}`;
|
|
} else if (ref.type === 'mute') {
|
|
type = `Muted${ctx.type}`;
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
const entry = {
|
|
created_at: ctx.created_at,
|
|
type,
|
|
displayName: ctx.displayName,
|
|
userId: ctx.userId,
|
|
isFavorite: ctx.isFavorite,
|
|
isFriend: ctx.isFriend,
|
|
tagColour: ctx.tagColour
|
|
};
|
|
notificationStore.queueGameLogNoty(entry);
|
|
if (
|
|
wristFilter[type] &&
|
|
(wristFilter[type] === 'Everyone' ||
|
|
(wristFilter[type] === 'Friends' && ctx.isFriend) ||
|
|
(wristFilter[type] === 'VIP' && ctx.isFavorite))
|
|
) {
|
|
addToSharedFeed(entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
function addTag(userId, colour) {
|
|
let changed = false;
|
|
for (const entry of sharedFeedData.value) {
|
|
if (entry.userId === userId) {
|
|
entry.tagColour = colour;
|
|
changed = true;
|
|
}
|
|
}
|
|
if (changed) {
|
|
sendSharedFeed();
|
|
}
|
|
}
|
|
|
|
async function sendSharedFeed() {
|
|
await AppApi.ExecuteVrOverlayFunction(
|
|
'wristFeedUpdate',
|
|
JSON.stringify(sharedFeedData.value)
|
|
);
|
|
}
|
|
|
|
return {
|
|
loadSharedFeed,
|
|
sendSharedFeed,
|
|
addEntry,
|
|
addTag,
|
|
sharedFeedData
|
|
};
|
|
});
|