2025-11-24 17:06:55 +02:00
|
|
|
import { mapState, mapActions } from 'pinia'
|
|
|
|
|
import { mapState as mapVuexState } from 'vuex'
|
2026-01-06 16:22:52 +02:00
|
|
|
import { v4 as uuidv4 } from 'uuid'
|
2025-11-24 17:06:55 +02:00
|
|
|
|
|
|
|
|
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
|
|
|
|
|
|
|
|
|
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
|
|
|
|
import ChoiceSetting from '../helpers/choice_setting.vue'
|
|
|
|
|
import UnitSetting from '../helpers/unit_setting.vue'
|
|
|
|
|
import IntegerSetting from '../helpers/integer_setting.vue'
|
|
|
|
|
import HelpIndicator from '../helpers/help_indicator.vue'
|
|
|
|
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
|
|
|
|
import Select from 'src/components/select/select.vue'
|
|
|
|
|
|
|
|
|
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
|
|
|
|
|
|
|
|
|
const ClutterTab = {
|
|
|
|
|
components: {
|
|
|
|
|
BooleanSetting,
|
|
|
|
|
ChoiceSetting,
|
|
|
|
|
UnitSetting,
|
|
|
|
|
IntegerSetting,
|
|
|
|
|
Checkbox,
|
|
|
|
|
Select,
|
2026-01-06 16:22:52 +02:00
|
|
|
HelpIndicator,
|
2025-11-24 17:06:55 +02:00
|
|
|
},
|
|
|
|
|
computed: {
|
2026-01-06 16:22:52 +02:00
|
|
|
instanceSpecificPanelPresent() {
|
|
|
|
|
return this.$store.state.instance.showInstanceSpecificPanel
|
|
|
|
|
},
|
2025-11-24 17:06:55 +02:00
|
|
|
...SharedComputedObject(),
|
2026-01-06 16:22:52 +02:00
|
|
|
...mapState(useServerSideStorageStore, {
|
|
|
|
|
muteFilters: (store) =>
|
|
|
|
|
Object.entries(store.prefsStorage.simple.muteFilters),
|
|
|
|
|
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
|
|
|
|
|
}),
|
2025-11-24 17:06:55 +02:00
|
|
|
...mapVuexState({
|
2026-01-06 16:22:52 +02:00
|
|
|
blockExpirationSupported: (state) => state.instance.blockExpiration,
|
2025-11-24 17:06:55 +02:00
|
|
|
}),
|
|
|
|
|
onMuteDefaultActionLv1: {
|
2026-01-06 16:22:52 +02:00
|
|
|
get() {
|
2025-11-24 17:06:55 +02:00
|
|
|
const value = this.$store.state.config.onMuteDefaultAction
|
|
|
|
|
if (value === 'ask' || value === 'forever') {
|
|
|
|
|
return value
|
|
|
|
|
} else {
|
|
|
|
|
return 'temporarily'
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
set(value) {
|
2025-11-24 17:06:55 +02:00
|
|
|
let realValue = value
|
|
|
|
|
if (value !== 'ask' && value !== 'forever') {
|
|
|
|
|
realValue = '14d'
|
|
|
|
|
}
|
2026-01-06 16:22:52 +02:00
|
|
|
this.$store.dispatch('setOption', {
|
|
|
|
|
name: 'onMuteDefaultAction',
|
|
|
|
|
value: realValue,
|
|
|
|
|
})
|
|
|
|
|
},
|
2025-11-24 17:06:55 +02:00
|
|
|
},
|
|
|
|
|
onBlockDefaultActionLv1: {
|
2026-01-06 16:22:52 +02:00
|
|
|
get() {
|
2025-11-24 17:06:55 +02:00
|
|
|
const value = this.$store.state.config.onBlockDefaultAction
|
|
|
|
|
if (value === 'ask' || value === 'forever') {
|
|
|
|
|
return value
|
|
|
|
|
} else {
|
|
|
|
|
return 'temporarily'
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
set(value) {
|
2025-11-24 17:06:55 +02:00
|
|
|
let realValue = value
|
|
|
|
|
if (value !== 'ask' && value !== 'forever') {
|
|
|
|
|
realValue = '14d'
|
|
|
|
|
}
|
2026-01-06 16:22:52 +02:00
|
|
|
this.$store.dispatch('setOption', {
|
|
|
|
|
name: 'onBlockDefaultAction',
|
|
|
|
|
value: realValue,
|
|
|
|
|
})
|
|
|
|
|
},
|
2025-11-24 17:06:55 +02:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
muteFiltersDraft() {
|
2025-11-24 17:06:55 +02:00
|
|
|
return Object.entries(this.muteFiltersDraftObject)
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
muteFiltersExpired() {
|
2025-11-24 17:06:55 +02:00
|
|
|
const now = Date.now()
|
2026-01-06 16:22:52 +02:00
|
|
|
return Object.entries(this.muteFiltersDraftObject).filter(
|
|
|
|
|
([, { expires }]) => expires != null && expires <= now,
|
|
|
|
|
)
|
|
|
|
|
},
|
2025-11-24 17:06:55 +02:00
|
|
|
},
|
|
|
|
|
methods: {
|
2026-01-06 16:22:52 +02:00
|
|
|
...mapActions(useServerSideStorageStore, [
|
|
|
|
|
'setPreference',
|
|
|
|
|
'unsetPreference',
|
|
|
|
|
'pushServerSideStorage',
|
|
|
|
|
]),
|
|
|
|
|
getDatetimeLocal(timestamp) {
|
2025-11-24 17:06:55 +02:00
|
|
|
const date = new Date(timestamp)
|
2026-01-06 16:22:52 +02:00
|
|
|
const fmt = new Intl.NumberFormat('en-US', { minimumIntegerDigits: 2 })
|
2025-11-24 17:06:55 +02:00
|
|
|
const datetime = [
|
|
|
|
|
date.getFullYear(),
|
|
|
|
|
'-',
|
|
|
|
|
fmt.format(date.getMonth() + 1),
|
|
|
|
|
'-',
|
|
|
|
|
fmt.format(date.getDate()),
|
|
|
|
|
'T',
|
|
|
|
|
fmt.format(date.getHours()),
|
|
|
|
|
':',
|
2026-01-06 16:22:52 +02:00
|
|
|
fmt.format(date.getMinutes()),
|
2025-11-24 17:06:55 +02:00
|
|
|
].join('')
|
|
|
|
|
return datetime
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
checkRegexValid(id) {
|
2025-11-24 17:06:55 +02:00
|
|
|
const filter = this.muteFiltersObject[id]
|
|
|
|
|
if (filter.type !== 'regexp') return true
|
|
|
|
|
if (filter.type !== 'user_regexp') return true
|
|
|
|
|
const { value } = filter
|
|
|
|
|
let valid = true
|
|
|
|
|
try {
|
|
|
|
|
new RegExp(value)
|
|
|
|
|
} catch {
|
|
|
|
|
valid = false
|
|
|
|
|
console.error('Invalid RegExp: ' + value)
|
|
|
|
|
}
|
|
|
|
|
return valid
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
createFilter(
|
|
|
|
|
filter = {
|
|
|
|
|
type: 'word',
|
|
|
|
|
value: '',
|
|
|
|
|
name: 'New Filter',
|
|
|
|
|
enabled: true,
|
|
|
|
|
expires: null,
|
|
|
|
|
hide: false,
|
|
|
|
|
},
|
|
|
|
|
) {
|
2025-11-24 17:06:55 +02:00
|
|
|
const newId = uuidv4()
|
|
|
|
|
|
|
|
|
|
filter.order = this.muteFilters.length + 2
|
|
|
|
|
this.muteFiltersDraftObject[newId] = filter
|
2026-01-06 16:22:52 +02:00
|
|
|
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
|
2025-11-24 17:06:55 +02:00
|
|
|
this.pushServerSideStorage()
|
|
|
|
|
},
|
|
|
|
|
exportFilter(id) {
|
|
|
|
|
this.exportedFilter = { ...this.muteFiltersDraftObject[id] }
|
|
|
|
|
delete this.exportedFilter.order
|
|
|
|
|
this.filterExporter.exportData()
|
|
|
|
|
},
|
|
|
|
|
importFilter() {
|
|
|
|
|
this.filterImporter.importData()
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
copyFilter(id) {
|
2025-11-24 17:06:55 +02:00
|
|
|
const filter = { ...this.muteFiltersDraftObject[id] }
|
|
|
|
|
const newId = uuidv4()
|
|
|
|
|
|
|
|
|
|
this.muteFiltersDraftObject[newId] = filter
|
2026-01-06 16:22:52 +02:00
|
|
|
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
|
2025-11-24 17:06:55 +02:00
|
|
|
this.pushServerSideStorage()
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
deleteFilter(id) {
|
2025-11-24 17:06:55 +02:00
|
|
|
delete this.muteFiltersDraftObject[id]
|
2026-01-06 16:22:52 +02:00
|
|
|
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
|
2025-11-24 17:06:55 +02:00
|
|
|
this.pushServerSideStorage()
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
purgeExpiredFilters() {
|
2025-11-24 17:06:55 +02:00
|
|
|
this.muteFiltersExpired.forEach(([id]) => {
|
|
|
|
|
delete this.muteFiltersDraftObject[id]
|
2026-01-06 16:22:52 +02:00
|
|
|
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
|
2025-11-24 17:06:55 +02:00
|
|
|
})
|
|
|
|
|
this.pushServerSideStorage()
|
|
|
|
|
},
|
|
|
|
|
updateFilter(id, field, value) {
|
|
|
|
|
const filter = { ...this.muteFiltersDraftObject[id] }
|
|
|
|
|
if (field === 'expires-never') {
|
|
|
|
|
if (!value) {
|
|
|
|
|
const offset = 1000 * 60 * 60 * 24 * 14 // 2 weeks
|
|
|
|
|
const date = Date.now() + offset
|
|
|
|
|
filter.expires = date
|
|
|
|
|
} else {
|
|
|
|
|
filter.expires = null
|
|
|
|
|
}
|
|
|
|
|
} else if (field === 'expires') {
|
|
|
|
|
const parsed = Date.parse(value)
|
|
|
|
|
filter.expires = parsed.valueOf()
|
|
|
|
|
} else {
|
|
|
|
|
filter[field] = value
|
|
|
|
|
}
|
|
|
|
|
this.muteFiltersDraftObject[id] = filter
|
|
|
|
|
this.muteFiltersDraftDirty[id] = true
|
|
|
|
|
},
|
|
|
|
|
saveFilter(id) {
|
2026-01-06 16:22:52 +02:00
|
|
|
this.setPreference({
|
|
|
|
|
path: 'simple.muteFilters.' + id,
|
|
|
|
|
value: this.muteFiltersDraftObject[id],
|
|
|
|
|
})
|
2025-11-24 17:06:55 +02:00
|
|
|
this.pushServerSideStorage()
|
|
|
|
|
this.muteFiltersDraftDirty[id] = false
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
// Updating nested properties
|
|
|
|
|
watch: {
|
2026-01-06 16:22:52 +02:00
|
|
|
replyVisibility() {
|
2025-11-24 17:06:55 +02:00
|
|
|
this.$store.dispatch('queueFlushAll')
|
2026-01-06 16:22:52 +02:00
|
|
|
},
|
|
|
|
|
},
|
2025-11-24 17:06:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default ClutterTab
|