This commit is contained in:
Henry Jameson 2026-03-06 16:34:53 +02:00
commit bcb13f3a49
4 changed files with 301 additions and 7 deletions

View file

@ -703,7 +703,7 @@ const users = {
commit('setCurrentUser', user)
useSyncConfigStore().initSyncConfig(user)
useUserHighlightStore().initHighlight(user)
useUserHighlightStore().initUserHighlight(user)
commit('addNewUsers', [user])
useEmojiStore().fetchEmoji()

View file

@ -169,16 +169,18 @@ export const _mergePrefs = (recent, stale) => {
`journal contains entry to edit internal (starts with _) field '${user}', something is incorrect here, ignoring.`,
)
}
console.log(resultOutput)
switch (operation) {
case 'set':
resultOutput[user] = args[0]
resultOutput.highlight[user] = args[0]
break
case 'unset':
delete resultOutput[user]
delete resultOutput.highlight[user]
break
default:
return console.error(`Unknown journal operation: '${operation}'`)
}
console.log(resultOutput)
})
return { ...resultOutput, _journal: totalJournal }
}
@ -260,7 +262,7 @@ export const useUserHighlightStore = defineStore('user_highlight', {
this.raw.highlight._journal = []
this.pushSyncConfig()
},
initHighlight(userData) {
initUserHighlight(userData) {
const live = userData.user_highlight
this.raw = live
let cache = this.cache
@ -319,12 +321,12 @@ export const useUserHighlightStore = defineStore('user_highlight', {
if (!needPush) return
this.updateCache({ username: window.vuex.state.users.currentUser.fqn })
const params = {
pleroma_settings_store: { 'user_highlight': this.cache },
pleroma_settings_store: { user_highlight: this.cache },
}
window.vuex.state.api.backendInteractor
.updateProfileJSON({ params })
.then((user) => {
this.initHighlight(user)
this.initUserHighlight(user)
this.dirty = false
})
},

View file

@ -16,7 +16,7 @@ import {
VERSION,
} from 'src/stores/sync_config.js'
describe('The SyncConfig module', () => {
describe('The SyncConfig store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})

View file

@ -0,0 +1,292 @@
import { cloneDeep } from 'lodash'
import { createPinia, setActivePinia } from 'pinia'
import {
_getRecentData,
_mergePrefs,
_moveItemInArray,
useUserHighlightStore,
} from 'src/stores/user_highlight.js'
describe('The UserHighlight store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
describe('mutations', () => {
describe('initUserHighlight', () => {
const user = {
created_at: new Date('1999-02-09'),
storage: {},
}
it('should initialize storage if none present', () => {
const store = useUserHighlightStore()
store.initUserHighlight({ ...user })
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.highlight).to.eql({ _journal: [] })
})
it('should initialize storage for new users if none present', () => {
const store = useUserHighlightStore()
store.initUserHighlight({ ...user, created_at: new Date() })
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.highlight).to.eql({ _journal: [] })
})
it('should use remote version if local missing', () => {
const store = useUserHighlightStore()
store.initUserHighlight(store, user)
expect(store.cache._timestamp).to.be.a('number')
})
})
describe('set', () => {
it('should set preference and update journal log accordingly', () => {
const store = useUserHighlightStore()
store.set({ user: 'highlight@testing', value: { type: 'test' }})
expect(store.highlight['highlight@testing']).to.eql({ user: 'highlight@testing', type: 'test' })
expect(store.highlight._journal.length).to.eql(1)
expect(store.highlight._journal[0]).to.eql({
user: 'highlight@testing',
operation: 'set',
args: [{ user: 'highlight@testing', type: 'test' }],
// should have A timestamp, we don't really care what it is
timestamp: store.highlight._journal[0].timestamp,
})
})
it('should keep journal to a minimum', () => {
const store = useUserHighlightStore()
store.set({ user: 'highlight@testing.xyz', value: { type: 'test' } })
store.set({ user: 'highlight@testing.xyz', value: { type: 'test' } })
store.updateCache({ username: 'test' })
expect(store.highlight['highlight@testing.xyz']).to.eql({ user: 'highlight@testing.xyz', type: 'test' })
expect(store.highlight._journal.length).to.eql(1)
expect(store.highlight._journal[0]).to.eql({
user: 'highlight@testing.xyz',
operation: 'set',
args: [{
user: 'highlight@testing.xyz',
type: 'test',
}],
// should have A timestamp, we don't really care what it is
timestamp: store.highlight._journal[0].timestamp,
})
})
it('should remove duplicate entries from journal', () => {
const store = useUserHighlightStore()
store.set({ user: 'a@test.xyz', value: { type: 'foo' } })
store.set({ user: 'a@test.xyz', value: { type: 'foo' } })
store.updateCache({ username: 'test' })
expect(store.highlight['a@test.xyz']).to.eql({ user: 'a@test.xyz', type: 'foo' })
expect(store.highlight._journal.length).to.eql(1)
})
})
})
describe('helper functions', () => {
describe('_getRecentData', () => {
it('should handle nulls correctly', () => {
expect(_getRecentData(null, null, true)).to.eql({
recent: null,
stale: null,
needUpload: true,
})
})
it("doesn't choke on invalid data", () => {
expect(_getRecentData({ a: 1 }, { b: 2 }, true)).to.eql({
recent: null,
stale: null,
needUpload: true,
})
})
it('should prefer the valid non-null correctly, needUpload works properly', () => {
const nonNull = { _timestamp: 1 }
expect(_getRecentData(nonNull, null, true)).to.eql({
recent: nonNull,
stale: null,
needUpload: true,
})
expect(_getRecentData(null, nonNull, true)).to.eql({
recent: nonNull,
stale: null,
needUpload: false,
})
})
it('should prefer the one with higher timestamp', () => {
const a = { _timestamp: 1 }
const b = { _timestamp: 2 }
expect(_getRecentData(a, b, true)).to.eql({
recent: b,
stale: a,
needUpload: false,
})
expect(_getRecentData(b, a, true)).to.eql({
recent: b,
stale: a,
needUpload: false,
})
})
it('case where both are same', () => {
const a = { _timestamp: 3 }
const b = { _timestamp: 3 }
expect(_getRecentData(a, b, true)).to.eql({
recent: b,
stale: a,
needUpload: false,
})
expect(_getRecentData(b, a, true)).to.eql({
recent: b,
stale: a,
needUpload: false,
})
})
})
describe('_mergePrefs', () => {
it('should prefer recent and apply journal to it', () => {
expect(
_mergePrefs(
// RECENT
{
highlight: { 'a@test.xyz': 1, 'b@test.xyz': 0, 'c@test.xyz': true },
_journal: [
{
user: 'b@test.xyz',
operation: 'set',
args: [0],
timestamp: 2,
},
{
user: 'c@test.xyz',
operation: 'set',
args: [true],
timestamp: 4,
},
],
},
// STALE
{
highlight: { 'a@test.xyz': 1, 'b@test.xyz': 1, 'c@test.xyz': false },
_journal: [
{
user: 'a@test.xyz',
operation: 'set',
args: [1],
timestamp: 1,
},
{
user: 'b@test.xyz',
operation: 'set',
args: [1],
timestamp: 3,
},
],
},
),
).to.eql({
highlight: { 'a@test.xyz': 1, 'b@test.xyz': 1, 'c@test.xyz': true },
_journal: [
{ user: 'a@test.xyz', operation: 'set', args: [1], timestamp: 1 },
{ user: 'b@test.xyz', operation: 'set', args: [1], timestamp: 3 },
{
user: 'c@test.xyz',
operation: 'set',
args: [true],
timestamp: 4,
},
],
})
})
it('should work with objects', () => {
expect(
_mergePrefs(
// RECENT
{
highlight: { 'a@test.xyz': { type: 'foo' } },
_journal: [
{
user: 'a@test.xyz',
operation: 'set',
args: [{ type: 'foo' }],
timestamp: 2,
},
],
},
// STALE
{
highlight: { 'a@test.xyz': { type: 'bar' } },
_journal: [
{
user: 'a@test.xyz',
operation: 'set',
args: [{ type: 'bar' }],
timestamp: 4,
},
],
},
),
).to.eql({
highlight: { 'a@test.xyz': { type: 'bar' } },
_journal: [
{
user: 'a@test.xyz',
operation: 'set',
args: [{ type: 'bar' }],
timestamp: 4,
},
],
})
})
it('should work with unset', () => {
expect(
_mergePrefs(
// RECENT
{
highlight: { 'a@test.xyz': { type: 'foo' } },
_journal: [
{
user: 'a@test.xyz',
operation: 'set',
args: [{ type: 'foo' }],
timestamp: 2,
},
],
},
// STALE
{
highlight: {},
_journal: [
{
user: 'a@test.xyz',
operation: 'unset',
args: [],
timestamp: 4,
},
],
},
),
).to.eql({
highlight: {},
_journal: [
{
user: 'a@test.xyz',
operation: 'unset',
args: [],
timestamp: 4,
},
],
})
})
})
})
})