mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 14:17:22 +01:00
Added cache for user styles on chat (#9679)
* Added cache for user styles on chat * Added loading on new message and other minor checks * Added null checks * Updated chat tests * Added costume preference to chat * Removed single profile cacheing for new chat messages * Remove owned gear from cache * Updated stats to only use buffs
This commit is contained in:
@@ -71,11 +71,9 @@ describe('DELETE /groups/:groupId/chat/:chatId', () => {
|
||||
});
|
||||
|
||||
it('returns the update chat when previous message parameter is passed and the chat is updated', async () => {
|
||||
await expect(user.del(`/groups/${groupWithChat._id}/chat/${nextMessage.id}?previousMsg=${message.id}`))
|
||||
.eventually
|
||||
.is.an('array')
|
||||
.to.include(message)
|
||||
.to.be.lengthOf(1);
|
||||
let deleteResult = await user.del(`/groups/${groupWithChat._id}/chat/${nextMessage.id}?previousMsg=${message.id}`);
|
||||
|
||||
expect(deleteResult[0].id).to.eql(message.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -364,6 +364,30 @@ describe('POST /chat', () => {
|
||||
expect(message.message.id).to.exist;
|
||||
});
|
||||
|
||||
it('creates a chat with user styles', async () => {
|
||||
const mount = 'test-mount';
|
||||
const pet = 'test-pet';
|
||||
const style = 'test-style';
|
||||
const userWithStyle = await generateUser({
|
||||
'items.currentMount': mount,
|
||||
'items.currentPet': pet,
|
||||
'preferences.style': style,
|
||||
});
|
||||
await userWithStyle.sync();
|
||||
|
||||
const message = await userWithStyle.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
||||
|
||||
expect(message.message.id).to.exist;
|
||||
expect(message.message.userStyles.items.currentMount).to.eql(userWithStyle.items.currentMount);
|
||||
expect(message.message.userStyles.items.currentPet).to.eql(userWithStyle.items.currentPet);
|
||||
expect(message.message.userStyles.preferences.style).to.eql(userWithStyle.preferences.style);
|
||||
expect(message.message.userStyles.preferences.hair).to.eql(userWithStyle.preferences.hair);
|
||||
expect(message.message.userStyles.preferences.skin).to.eql(userWithStyle.preferences.skin);
|
||||
expect(message.message.userStyles.preferences.shirt).to.eql(userWithStyle.preferences.shirt);
|
||||
expect(message.message.userStyles.preferences.chair).to.eql(userWithStyle.preferences.chair);
|
||||
expect(message.message.userStyles.preferences.background).to.eql(userWithStyle.preferences.background);
|
||||
});
|
||||
|
||||
it('adds backer info to chat', async () => {
|
||||
const backerInfo = {
|
||||
npc: 'Town Crier',
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
.row(v-if='user._id !== msg.uuid')
|
||||
div(:class='inbox ? "col-4" : "col-2"')
|
||||
avatar(
|
||||
v-if='cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected',
|
||||
:member="cachedProfileData[msg.uuid]",
|
||||
v-if='msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)',
|
||||
:member="msg.userStyles || cachedProfileData[msg.uuid]",
|
||||
:avatarOnly="true",
|
||||
:hideClassBadge='true',
|
||||
@click.native="showMemberModal(msg.uuid)",
|
||||
@@ -36,8 +36,8 @@
|
||||
@show-member-modal='showMemberModal')
|
||||
div(:class='inbox ? "col-4" : "col-2"')
|
||||
avatar(
|
||||
v-if='cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected',
|
||||
:member="cachedProfileData[msg.uuid]",
|
||||
v-if='msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)',
|
||||
:member="msg.userStyles || cachedProfileData[msg.uuid]",
|
||||
:avatarOnly="true",
|
||||
:hideClassBadge='true',
|
||||
@click.native="showMemberModal(msg.uuid)",
|
||||
@@ -117,12 +117,12 @@ export default {
|
||||
// @TODO: We need a different lazy load mechnism.
|
||||
// But honestly, adding a paging route to chat would solve this
|
||||
messages () {
|
||||
this.loadProfileCache();
|
||||
return this.chat;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
messages (oldValue, newValue) {
|
||||
if (newValue.length === oldValue.length) return;
|
||||
messages () {
|
||||
this.loadProfileCache();
|
||||
},
|
||||
},
|
||||
@@ -139,18 +139,28 @@ export default {
|
||||
this._loadProfileCache(screenPosition);
|
||||
}, 1000),
|
||||
async _loadProfileCache (screenPosition) {
|
||||
if (this.loading) return;
|
||||
this.loading = true;
|
||||
|
||||
let promises = [];
|
||||
const noProfilesLoaded = Object.keys(this.cachedProfileData).length === 0;
|
||||
|
||||
// @TODO: write an explination
|
||||
if (screenPosition && Math.floor(screenPosition) + 1 > this.currentProfileLoadedEnd / 10) {
|
||||
// @TODO: Remove this after enough messages are cached
|
||||
if (!noProfilesLoaded && screenPosition && Math.floor(screenPosition) + 1 > this.currentProfileLoadedEnd / 10) {
|
||||
this.currentProfileLoadedEnd = 10 * (Math.floor(screenPosition) + 1);
|
||||
} else if (screenPosition) {
|
||||
} else if (!noProfilesLoaded && screenPosition) {
|
||||
return;
|
||||
}
|
||||
|
||||
let aboutToCache = {};
|
||||
this.messages.forEach(message => {
|
||||
let uuid = message.uuid;
|
||||
|
||||
if (message.userStyles) {
|
||||
this.$set(this.cachedProfileData, uuid, message.userStyles);
|
||||
}
|
||||
|
||||
if (Boolean(uuid) && !this.cachedProfileData[uuid] && !aboutToCache[uuid]) {
|
||||
if (uuid === 'system' || this.currentProfileLoadedCount === this.currentProfileLoadedEnd) return;
|
||||
aboutToCache[uuid] = {};
|
||||
@@ -176,6 +186,8 @@ export default {
|
||||
this.$set(this.cachedProfileData, uuid, {rejected: true});
|
||||
}
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
},
|
||||
displayDivider (message) {
|
||||
if (this.currentDayDividerDisplay !== moment(message.timestamp).day()) {
|
||||
|
||||
@@ -466,9 +466,54 @@ export function chatDefaults (msg, user) {
|
||||
return message;
|
||||
}
|
||||
|
||||
function setUserStyles (newMessage, user) {
|
||||
let userStyles = {};
|
||||
userStyles.items = {gear: {}};
|
||||
|
||||
let userCopy = user;
|
||||
if (user.toObject) userCopy = user.toObject();
|
||||
|
||||
if (userCopy.items) {
|
||||
userStyles.items.gear = {};
|
||||
userStyles.items.gear.costume = Object.assign({}, userCopy.items.gear.costume);
|
||||
userStyles.items.gear.equipped = Object.assign({}, userCopy.items.gear.equipped);
|
||||
|
||||
userStyles.items.currentMount = userCopy.items.currentMount;
|
||||
userStyles.items.currentPet = userCopy.items.currentPet;
|
||||
}
|
||||
|
||||
|
||||
if (userCopy.preferences) {
|
||||
userStyles.preferences = {};
|
||||
if (userCopy.preferences.style) userStyles.preferences.style = userCopy.preferences.style;
|
||||
userStyles.preferences.hair = userCopy.preferences.hair;
|
||||
userStyles.preferences.skin = userCopy.preferences.skin;
|
||||
userStyles.preferences.shirt = userCopy.preferences.shirt;
|
||||
userStyles.preferences.chair = userCopy.preferences.chair;
|
||||
userStyles.preferences.size = userCopy.preferences.size;
|
||||
userStyles.preferences.chair = userCopy.preferences.chair;
|
||||
userStyles.preferences.background = userCopy.preferences.background;
|
||||
userStyles.preferences.costume = userCopy.preferences.costume;
|
||||
}
|
||||
|
||||
userStyles.stats = {};
|
||||
if (userCopy.stats && userCopy.stats.buffs) {
|
||||
userStyles.stats.buffs = {
|
||||
seafoam: userCopy.stats.buffs.seafoam,
|
||||
shinySeed: userCopy.stats.buffs.shinySeed,
|
||||
spookySparkles: userCopy.stats.buffs.spookySparkles,
|
||||
snowball: userCopy.stats.buffs.snowball,
|
||||
};
|
||||
}
|
||||
|
||||
newMessage.userStyles = userStyles;
|
||||
}
|
||||
|
||||
schema.methods.sendChat = function sendChat (message, user, metaData) {
|
||||
let newMessage = chatDefaults(message, user);
|
||||
|
||||
if (user) setUserStyles(newMessage, user);
|
||||
|
||||
// Optional data stored in the chat message but not returned
|
||||
// to the users that can be stored for debugging purposes
|
||||
if (metaData) {
|
||||
|
||||
Reference in New Issue
Block a user