mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-12 19:33:50 +02:00
650 lines
24 KiB
JavaScript
650 lines
24 KiB
JavaScript
import { reactive, ref } from 'vue';
|
|
import { defineStore } from 'pinia';
|
|
|
|
import { groupRequest, worldRequest } from '../api';
|
|
import { useFeedStore } from './feed';
|
|
import { useFriendStore } from './friend';
|
|
import { useGameLogStore } from './gameLog';
|
|
import { useGroupStore } from './group';
|
|
import { useInstanceStore } from './instance';
|
|
import { useLocationStore } from './location';
|
|
import { useModerationStore } from './moderation';
|
|
import { useNotificationStore } from './notification';
|
|
import { useNotificationsSettingsStore } from './settings/notifications';
|
|
import { usePhotonStore } from './photon';
|
|
import { useUserStore } from './user';
|
|
import { useWorldStore } from './world';
|
|
import { useWristOverlaySettingsStore } from './settings/wristOverlay';
|
|
import { watchState } from '../service/watchState';
|
|
|
|
import * as workerTimers from 'worker-timers';
|
|
|
|
export const useSharedFeedStore = defineStore('SharedFeed', () => {
|
|
const friendStore = useFriendStore();
|
|
const notificationsSettingsStore = useNotificationsSettingsStore();
|
|
const locationStore = useLocationStore();
|
|
const groupStore = useGroupStore();
|
|
const userStore = useUserStore();
|
|
const wristOverlaySettingsStore = useWristOverlaySettingsStore();
|
|
const instanceStore = useInstanceStore();
|
|
const gameLogStore = useGameLogStore();
|
|
const moderationStore = useModerationStore();
|
|
const notificationStore = useNotificationStore();
|
|
const feedStore = useFeedStore();
|
|
const worldStore = useWorldStore();
|
|
const photonStore = usePhotonStore();
|
|
|
|
const state = reactive({
|
|
updateSharedFeedTimer: null,
|
|
updateSharedFeedPending: false,
|
|
updateSharedFeedPendingForceUpdate: false
|
|
});
|
|
|
|
const sharedFeed = ref({
|
|
gameLog: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
feedTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
notificationTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
friendLogTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
moderationAgainstTable: {
|
|
wrist: [],
|
|
lastEntryDate: ''
|
|
},
|
|
pendingUpdate: false
|
|
});
|
|
|
|
function updateSharedFeed(forceUpdate) {
|
|
if (!watchState.isFriendsLoaded) {
|
|
return;
|
|
}
|
|
// TODO: remove debounce, decouple blocked player join/leave notifications, pull data from database with filters instead of sharedFeed
|
|
if (state.updateSharedFeedTimer) {
|
|
if (forceUpdate) {
|
|
state.updateSharedFeedPendingForceUpdate = true;
|
|
}
|
|
state.updateSharedFeedPending = true;
|
|
} else {
|
|
updateSharedExecute(forceUpdate);
|
|
state.updateSharedFeedTimer = setTimeout(() => {
|
|
if (state.updateSharedFeedPending) {
|
|
updateSharedExecute(
|
|
state.updateSharedFeedPendingForceUpdate
|
|
);
|
|
}
|
|
state.updateSharedFeedTimer = null;
|
|
}, 150);
|
|
}
|
|
}
|
|
|
|
function updateSharedExecute(forceUpdate) {
|
|
try {
|
|
updateSharedFeedDebounce(forceUpdate);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
state.updateSharedFeedTimer = null;
|
|
state.updateSharedFeedPending = false;
|
|
state.updateSharedFeedPendingForceUpdate = false;
|
|
}
|
|
|
|
function updateSharedFeedDebounce(forceUpdate) {
|
|
updateSharedFeedGameLog(forceUpdate);
|
|
updateSharedFeedFeedTable(forceUpdate);
|
|
updateSharedFeedNotificationTable(forceUpdate);
|
|
updateSharedFeedFriendLogTable(forceUpdate);
|
|
updateSharedFeedModerationAgainstTable(forceUpdate);
|
|
const feeds = sharedFeed.value;
|
|
if (!feeds.pendingUpdate) {
|
|
return;
|
|
}
|
|
let wristFeed = [];
|
|
wristFeed = wristFeed.concat(
|
|
feeds.gameLog.wrist,
|
|
feeds.feedTable.wrist,
|
|
feeds.notificationTable.wrist,
|
|
feeds.friendLogTable.wrist,
|
|
feeds.moderationAgainstTable.wrist
|
|
);
|
|
// OnPlayerJoining/Traveling
|
|
userStore.currentTravelers.forEach((ref) => {
|
|
const isFavorite = friendStore.localFavoriteFriends.has(ref.id);
|
|
if (
|
|
(notificationsSettingsStore.sharedFeedFilters.wrist
|
|
.OnPlayerJoining === 'Friends' ||
|
|
(notificationsSettingsStore.sharedFeedFilters.wrist
|
|
.OnPlayerJoining === 'VIP' &&
|
|
isFavorite)) &&
|
|
!locationStore.lastLocation.playerList.has(ref.id)
|
|
) {
|
|
if (ref.$location.tag === locationStore.lastLocation.location) {
|
|
var feedEntry = {
|
|
...ref,
|
|
isFavorite,
|
|
isFriend: true,
|
|
type: 'OnPlayerJoining'
|
|
};
|
|
wristFeed.unshift(feedEntry);
|
|
} else {
|
|
const worldRef = worldStore.cachedWorlds.get(
|
|
ref.$location.worldId
|
|
);
|
|
let groupName = '';
|
|
if (ref.$location.groupId) {
|
|
const groupRef = groupStore.cachedGroups.get(
|
|
ref.$location.groupId
|
|
);
|
|
if (typeof groupRef !== 'undefined') {
|
|
groupName = groupRef.name;
|
|
} else {
|
|
// no group cache, fetch group and try again
|
|
groupRequest
|
|
.getGroup({
|
|
groupId: ref.$location.groupId
|
|
})
|
|
.then((args) => {
|
|
args.ref = groupStore.applyGroup(args.json);
|
|
workerTimers.setTimeout(() => {
|
|
// delay to allow for group cache to update
|
|
sharedFeed.value.pendingUpdate = true;
|
|
updateSharedFeed(false);
|
|
}, 100);
|
|
return args;
|
|
})
|
|
.catch((err) => {
|
|
console.error(err);
|
|
});
|
|
}
|
|
}
|
|
if (typeof worldRef !== 'undefined') {
|
|
let 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
|
|
worldRequest
|
|
.getWorld({
|
|
worldId: ref.$location.worldId
|
|
})
|
|
.then((args) => {
|
|
workerTimers.setTimeout(() => {
|
|
// delay to allow for world cache to update
|
|
sharedFeed.value.pendingUpdate = true;
|
|
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);
|
|
// temp fix, tack on instance names in the worst way possible
|
|
for (let feedEntry of wristFeed) {
|
|
if (feedEntry.location) {
|
|
const instanceRef = instanceStore.cachedInstances.get(
|
|
feedEntry.location
|
|
);
|
|
if (instanceRef?.displayName) {
|
|
feedEntry.instanceDisplayName = instanceRef.displayName;
|
|
}
|
|
}
|
|
// invites
|
|
if (feedEntry.details?.worldId) {
|
|
const instanceRef = instanceStore.cachedInstances.get(
|
|
feedEntry.details.worldId
|
|
);
|
|
if (instanceRef?.displayName) {
|
|
feedEntry.instanceDisplayName = instanceRef.displayName;
|
|
}
|
|
}
|
|
}
|
|
AppApi.ExecuteVrFeedFunction(
|
|
'wristFeedUpdate',
|
|
JSON.stringify(wristFeed)
|
|
);
|
|
userStore.applyUserDialogLocation();
|
|
instanceStore.applyWorldDialogInstances();
|
|
instanceStore.applyGroupDialogInstances();
|
|
feeds.pendingUpdate = false;
|
|
}
|
|
|
|
function updateSharedFeedGameLog(forceUpdate) {
|
|
// Location, OnPlayerJoined, OnPlayerLeft
|
|
const sessionTable = gameLogStore.gameLogSessionTable;
|
|
let i = sessionTable.length;
|
|
if (i > 0) {
|
|
if (
|
|
sessionTable[i - 1].created_at ===
|
|
sharedFeed.value.gameLog.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
sharedFeed.value.gameLog.lastEntryDate =
|
|
sessionTable[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
const bias = new Date(Date.now() - 1000 * 60 * 60 * 12).toJSON(); // 12 hours
|
|
const wristArr = [];
|
|
let w = 0;
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
let currentUserLeaveTime = 0;
|
|
let locationJoinTime = 0;
|
|
let earliestKeptTime = 0;
|
|
for (i = sessionTable.length - 1; i > -1; i--) {
|
|
const ctx = sessionTable[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.type === 'Notification') {
|
|
continue;
|
|
}
|
|
let ctxTime = 0;
|
|
if (w >= 50 && earliestKeptTime > 0) {
|
|
ctxTime = Date.parse(ctx.created_at);
|
|
if (ctxTime < earliestKeptTime - 20 * 1000) {
|
|
break;
|
|
}
|
|
}
|
|
// 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--;
|
|
}
|
|
}
|
|
}
|
|
// remove current user
|
|
if (
|
|
(ctx.type === 'OnPlayerJoined' ||
|
|
ctx.type === 'OnPlayerLeft' ||
|
|
ctx.type === 'PortalSpawn') &&
|
|
ctx.displayName === userStore.currentUser.displayName
|
|
) {
|
|
continue;
|
|
}
|
|
let isFriend = false;
|
|
let isFavorite = false;
|
|
if (ctx.userId) {
|
|
isFriend = friendStore.friends.has(ctx.userId);
|
|
isFavorite = friendStore.localFavoriteFriends.has(ctx.userId);
|
|
} else if (ctx.displayName) {
|
|
for (let ref of userStore.cachedUsers.values()) {
|
|
if (ref.displayName === ctx.displayName) {
|
|
isFriend = friendStore.friends.has(ref.id);
|
|
isFavorite = friendStore.localFavoriteFriends.has(
|
|
ref.id
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// add tag colour
|
|
let tagColour = '';
|
|
if (ctx.userId) {
|
|
const tagRef = userStore.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 moderationStore.cachedPlayerModerations.values()) {
|
|
if (
|
|
ref.targetDisplayName !== ctx.displayName &&
|
|
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: ref.targetDisplayName,
|
|
userId: ref.targetUserId,
|
|
isFriend,
|
|
isFavorite
|
|
};
|
|
if (
|
|
wristFilter[type] &&
|
|
(wristFilter[type] === 'Everyone' ||
|
|
(wristFilter[type] === 'Friends' && isFriend) ||
|
|
(wristFilter[type] === 'VIP' && isFavorite))
|
|
) {
|
|
wristArr.unshift(entry);
|
|
}
|
|
notificationStore.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;
|
|
if (!ctxTime) {
|
|
ctxTime = Date.parse(ctx.created_at);
|
|
}
|
|
if (!earliestKeptTime || ctxTime < earliestKeptTime) {
|
|
earliestKeptTime = ctxTime;
|
|
}
|
|
}
|
|
}
|
|
wristArr.splice(50);
|
|
sharedFeed.value.gameLog.wrist = wristArr;
|
|
sharedFeed.value.pendingUpdate = true;
|
|
}
|
|
|
|
function updateSharedFeedFeedTable(forceUpdate) {
|
|
// GPS, Online, Offline, Status, Avatar
|
|
const feedSession = feedStore.feedSessionTable;
|
|
var i = feedSession.length;
|
|
if (i > 0) {
|
|
if (
|
|
feedSession[i - 1].created_at ===
|
|
sharedFeed.value.feedTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
sharedFeed.value.feedTable.lastEntryDate =
|
|
feedSession[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
const bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
const wristArr = [];
|
|
let w = 0;
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
for (let i = feedSession.length - 1; i > -1; i--) {
|
|
const ctx = feedSession[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.type === 'Avatar') {
|
|
continue;
|
|
}
|
|
// hide private worlds from feed
|
|
if (
|
|
wristOverlaySettingsStore.hidePrivateFromFeed &&
|
|
ctx.type === 'GPS' &&
|
|
ctx.location === 'private'
|
|
) {
|
|
continue;
|
|
}
|
|
const isFriend = friendStore.friends.has(ctx.userId);
|
|
const isFavorite = friendStore.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;
|
|
}
|
|
}
|
|
sharedFeed.value.feedTable.wrist = wristArr;
|
|
sharedFeed.value.pendingUpdate = true;
|
|
}
|
|
|
|
function updateSharedFeedNotificationTable(forceUpdate) {
|
|
// invite, requestInvite, requestInviteResponse, inviteResponse, friendRequest
|
|
const notificationTable = notificationStore.notificationTable.data;
|
|
let i = notificationTable.length;
|
|
if (i > 0) {
|
|
if (
|
|
notificationTable[i - 1].created_at ===
|
|
sharedFeed.value.notificationTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
sharedFeed.value.notificationTable.lastEntryDate =
|
|
notificationTable[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
const bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
const wristArr = [];
|
|
let w = 0;
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
for (i = notificationTable.length - 1; i > -1; i--) {
|
|
const ctx = notificationTable[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.senderUserId === userStore.currentUser.id) {
|
|
continue;
|
|
}
|
|
const isFriend = friendStore.friends.has(ctx.senderUserId);
|
|
const isFavorite = friendStore.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;
|
|
}
|
|
}
|
|
sharedFeed.value.notificationTable.wrist = wristArr;
|
|
sharedFeed.value.pendingUpdate = true;
|
|
}
|
|
|
|
function updateSharedFeedFriendLogTable(forceUpdate) {
|
|
// TrustLevel, Friend, FriendRequest, Unfriend, DisplayName
|
|
const friendLog = friendStore.friendLogTable.data;
|
|
var i = friendLog.length;
|
|
if (i > 0) {
|
|
if (
|
|
friendLog[i - 1].created_at ===
|
|
sharedFeed.value.friendLogTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
sharedFeed.value.friendLogTable.lastEntryDate =
|
|
friendLog[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
const bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
const wristArr = [];
|
|
let w = 0;
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
for (let i = friendLog.length - 1; i > -1; i--) {
|
|
const ctx = friendLog[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
if (ctx.type === 'FriendRequest') {
|
|
continue;
|
|
}
|
|
const isFriend = friendStore.friends.has(ctx.userId);
|
|
const isFavorite = friendStore.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;
|
|
}
|
|
}
|
|
sharedFeed.value.friendLogTable.wrist = wristArr;
|
|
sharedFeed.value.pendingUpdate = true;
|
|
}
|
|
|
|
function updateSharedFeedModerationAgainstTable(forceUpdate) {
|
|
// Unblocked, Blocked, Muted, Unmuted
|
|
const moderationAgainst = photonStore.moderationAgainstTable;
|
|
var i = moderationAgainst.length;
|
|
if (i > 0) {
|
|
if (
|
|
moderationAgainst[i - 1].created_at ===
|
|
sharedFeed.value.moderationAgainstTable.lastEntryDate &&
|
|
forceUpdate === false
|
|
) {
|
|
return;
|
|
}
|
|
sharedFeed.value.moderationAgainstTable.lastEntryDate =
|
|
moderationAgainst[i - 1].created_at;
|
|
} else {
|
|
return;
|
|
}
|
|
const bias = new Date(Date.now() - 86400000).toJSON(); // 24 hours
|
|
const wristArr = [];
|
|
let w = 0;
|
|
const wristFilter = notificationsSettingsStore.sharedFeedFilters.wrist;
|
|
for (let i = moderationAgainst.length - 1; i > -1; i--) {
|
|
const ctx = moderationAgainst[i];
|
|
if (ctx.created_at < bias) {
|
|
break;
|
|
}
|
|
const isFriend = friendStore.friends.has(ctx.userId);
|
|
const isFavorite = friendStore.localFavoriteFriends.has(ctx.userId);
|
|
// add tag colour
|
|
let tagColour = '';
|
|
const tagRef = userStore.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;
|
|
}
|
|
}
|
|
sharedFeed.value.moderationAgainstTable.wrist = wristArr;
|
|
sharedFeed.value.pendingUpdate = true;
|
|
}
|
|
|
|
return {
|
|
state,
|
|
sharedFeed,
|
|
updateSharedFeed
|
|
};
|
|
});
|