aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/api.js9
-rw-r--r--src/modules/config.js1
-rw-r--r--src/modules/editStatus.js25
-rw-r--r--src/modules/instance.js149
-rw-r--r--src/modules/statusHistory.js25
-rw-r--r--src/modules/statuses.js9
-rw-r--r--src/modules/users.js8
7 files changed, 209 insertions, 17 deletions
diff --git a/src/modules/api.js b/src/modules/api.js
index f783fa4f..0acc03f1 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -16,7 +16,7 @@ const api = {
followRequests: []
},
getters: {
- followRequestCount: state => state.api.followRequests.length
+ followRequestCount: state => state.followRequests.length
},
mutations: {
setBackendInteractor (state, backendInteractor) {
@@ -103,6 +103,13 @@ const api = {
showImmediately: timelineData.visibleStatuses.length === 0,
timeline: 'friends'
})
+ } else if (message.event === 'status.update') {
+ dispatch('addNewStatuses', {
+ statuses: [message.status],
+ userId: false,
+ showImmediately: message.status.id in timelineData.visibleStatusesObject,
+ timeline: 'friends'
+ })
} else if (message.event === 'delete') {
dispatch('deleteStatusById', message.id)
} else if (message.event === 'pleroma:chat_update') {
diff --git a/src/modules/config.js b/src/modules/config.js
index eeaac917..c966602e 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -183,6 +183,7 @@ const config = {
break
case 'interfaceLanguage':
messages.setLanguage(this.getters.i18n, value)
+ dispatch('loadUnicodeEmojiData', value)
Cookies.set(BACKEND_LANGUAGE_COOKIE_NAME, localeService.internalToBackendLocale(value))
break
case 'thirdColumnMode':
diff --git a/src/modules/editStatus.js b/src/modules/editStatus.js
new file mode 100644
index 00000000..fd316519
--- /dev/null
+++ b/src/modules/editStatus.js
@@ -0,0 +1,25 @@
+const editStatus = {
+ state: {
+ params: null,
+ modalActivated: false
+ },
+ mutations: {
+ openEditStatusModal (state, params) {
+ state.params = params
+ state.modalActivated = true
+ },
+ closeEditStatusModal (state) {
+ state.modalActivated = false
+ }
+ },
+ actions: {
+ openEditStatusModal ({ commit }, params) {
+ commit('openEditStatusModal', params)
+ },
+ closeEditStatusModal ({ commit }) {
+ commit('closeEditStatusModal')
+ }
+ }
+}
+
+export default editStatus
diff --git a/src/modules/instance.js b/src/modules/instance.js
index bfce6f38..b1bc9779 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -2,6 +2,39 @@ import { getPreset, applyTheme } from '../services/style_setter/style_setter.js'
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
import apiService from '../services/api/api.service.js'
import { instanceDefaultProperties } from './config.js'
+import { langCodeToCldrName, ensureFinalFallback } from '../i18n/languages.js'
+
+const SORTED_EMOJI_GROUP_IDS = [
+ 'smileys-and-emotion',
+ 'people-and-body',
+ 'animals-and-nature',
+ 'food-and-drink',
+ 'travel-and-places',
+ 'activities',
+ 'objects',
+ 'symbols',
+ 'flags'
+]
+
+const REGIONAL_INDICATORS = (() => {
+ const start = 0x1F1E6
+ const end = 0x1F1FF
+ const A = 'A'.codePointAt(0)
+ const res = new Array(end - start + 1)
+ for (let i = start; i <= end; ++i) {
+ const letter = String.fromCodePoint(A + i - start)
+ res[i - start] = {
+ replacement: String.fromCodePoint(i),
+ imageUrl: false,
+ displayText: 'regional_indicator_' + letter,
+ displayTextI18n: {
+ key: 'emoji.regional_indicator',
+ args: { letter }
+ }
+ }
+ }
+ return res
+})()
const defaultState = {
// Stuff from apiConfig
@@ -64,8 +97,9 @@ const defaultState = {
// Nasty stuff
customEmoji: [],
customEmojiFetched: false,
- emoji: [],
+ emoji: {},
emojiFetched: false,
+ unicodeEmojiAnnotations: {},
pleromaBackend: true,
postFormats: [],
restrictedNicknames: [],
@@ -97,6 +131,31 @@ const defaultState = {
}
}
+const loadAnnotations = (lang) => {
+ return import(
+ /* webpackChunkName: "emoji-annotations/[request]" */
+ `@kazvmoe-infra/unicode-emoji-json/annotations/${langCodeToCldrName(lang)}.json`
+ )
+ .then(k => k.default)
+}
+
+const injectAnnotations = (emoji, annotations) => {
+ const availableLangs = Object.keys(annotations)
+
+ return {
+ ...emoji,
+ annotations: availableLangs.reduce((acc, cur) => {
+ acc[cur] = annotations[cur][emoji.replacement]
+ return acc
+ }, {})
+ }
+}
+
+const injectRegionalIndicators = groups => {
+ groups.symbols.push(...REGIONAL_INDICATORS)
+ return groups
+}
+
const instance = {
state: defaultState,
mutations: {
@@ -107,6 +166,9 @@ const instance = {
},
setKnownDomains (state, domains) {
state.knownDomains = domains
+ },
+ setUnicodeEmojiAnnotations (state, { lang, annotations }) {
+ state.unicodeEmojiAnnotations[lang] = annotations
}
},
getters: {
@@ -115,6 +177,41 @@ const instance = {
.map(key => [key, state[key]])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
},
+ groupedCustomEmojis (state) {
+ const packsOf = emoji => {
+ return emoji.tags
+ .filter(k => k.startsWith('pack:'))
+ .map(k => k.slice(5)) // remove 'pack:' prefix
+ }
+
+ return state.customEmoji
+ .reduce((res, emoji) => {
+ packsOf(emoji).forEach(packName => {
+ const packId = `custom-${packName}`
+ if (!res[packId]) {
+ res[packId] = ({
+ id: packId,
+ text: packName,
+ image: emoji.imageUrl,
+ emojis: []
+ })
+ }
+ res[packId].emojis.push(emoji)
+ })
+ return res
+ }, {})
+ },
+ standardEmojiList (state) {
+ return SORTED_EMOJI_GROUP_IDS
+ .map(groupId => (state.emoji[groupId] || []).map(k => injectAnnotations(k, state.unicodeEmojiAnnotations)))
+ .reduce((a, b) => a.concat(b), [])
+ },
+ standardEmojiGroupList (state) {
+ return SORTED_EMOJI_GROUP_IDS.map(groupId => ({
+ id: groupId,
+ emojis: (state.emoji[groupId] || []).map(k => injectAnnotations(k, state.unicodeEmojiAnnotations))
+ }))
+ },
instanceDomain (state) {
return new URL(state.server).hostname
}
@@ -138,32 +235,52 @@ const instance = {
},
async getStaticEmoji ({ commit }) {
try {
- const res = await window.fetch('/static/emoji.json')
- if (res.ok) {
- const values = await res.json()
- const emoji = Object.keys(values).map((key) => {
- return {
- displayText: key,
- imageUrl: false,
- replacement: values[key]
- }
- }).sort((a, b) => a.name > b.name ? 1 : -1)
- commit('setInstanceOption', { name: 'emoji', value: emoji })
- } else {
- throw (res)
- }
+ const values = (await import(/* webpackChunkName: 'emoji' */ '../../static/emoji.json')).default
+
+ const emoji = Object.keys(values).reduce((res, groupId) => {
+ res[groupId] = values[groupId].map(e => ({
+ displayText: e.slug,
+ imageUrl: false,
+ replacement: e.emoji
+ }))
+ return res
+ }, {})
+ commit('setInstanceOption', { name: 'emoji', value: injectRegionalIndicators(emoji) })
} catch (e) {
console.warn("Can't load static emoji")
console.warn(e)
}
},
+ loadUnicodeEmojiData ({ commit, state }, language) {
+ const langList = ensureFinalFallback(language)
+
+ return Promise.all(
+ langList
+ .map(async lang => {
+ if (!state.unicodeEmojiAnnotations[lang]) {
+ const annotations = await loadAnnotations(lang)
+ commit('setUnicodeEmojiAnnotations', { lang, annotations })
+ }
+ }))
+ },
+
async getCustomEmoji ({ commit, state }) {
try {
const res = await window.fetch('/api/pleroma/emoji.json')
if (res.ok) {
const result = await res.json()
const values = Array.isArray(result) ? Object.assign({}, ...result) : result
+ const caseInsensitiveStrCmp = (a, b) => {
+ const la = a.toLowerCase()
+ const lb = b.toLowerCase()
+ return la > lb ? 1 : (la < lb ? -1 : 0)
+ }
+ const byPackThenByName = (a, b) => {
+ const packOf = emoji => (emoji.tags.filter(k => k.startsWith('pack:'))[0] || '').slice(5)
+ return caseInsensitiveStrCmp(packOf(a), packOf(b)) || caseInsensitiveStrCmp(a.displayText, b.displayText)
+ }
+
const emoji = Object.entries(values).map(([key, value]) => {
const imageUrl = value.image_url
return {
@@ -174,7 +291,7 @@ const instance = {
}
// Technically could use tags but those are kinda useless right now,
// should have been "pack" field, that would be more useful
- }).sort((a, b) => a.displayText.toLowerCase() > b.displayText.toLowerCase() ? 1 : -1)
+ }).sort(byPackThenByName)
commit('setInstanceOption', { name: 'customEmoji', value: emoji })
} else {
throw (res)
diff --git a/src/modules/statusHistory.js b/src/modules/statusHistory.js
new file mode 100644
index 00000000..db3d6d4b
--- /dev/null
+++ b/src/modules/statusHistory.js
@@ -0,0 +1,25 @@
+const statusHistory = {
+ state: {
+ params: {},
+ modalActivated: false
+ },
+ mutations: {
+ openStatusHistoryModal (state, params) {
+ state.params = params
+ state.modalActivated = true
+ },
+ closeStatusHistoryModal (state) {
+ state.modalActivated = false
+ }
+ },
+ actions: {
+ openStatusHistoryModal ({ commit }, params) {
+ commit('openStatusHistoryModal', params)
+ },
+ closeStatusHistoryModal ({ commit }) {
+ commit('closeStatusHistoryModal')
+ }
+ }
+}
+
+export default statusHistory
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 4aa04683..803d7019 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -249,6 +249,9 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
status: (status) => {
addStatus(status, showImmediately)
},
+ edit: (status) => {
+ addStatus(status, showImmediately)
+ },
retweet: (status) => {
// RetweetedStatuses are never shown immediately
const retweetedStatus = addStatus(status.retweeted_status, false, false)
@@ -606,6 +609,12 @@ const statuses = {
return rootState.api.backendInteractor.fetchStatus({ id })
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
},
+ fetchStatusSource ({ rootState, dispatch }, status) {
+ return apiService.fetchStatusSource({ id: status.id, credentials: rootState.users.currentUser.credentials })
+ },
+ fetchStatusHistory ({ rootState, dispatch }, status) {
+ return apiService.fetchStatusHistory({ status })
+ },
deleteStatus ({ rootState, commit }, status) {
commit('setDeleted', { status })
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
diff --git a/src/modules/users.js b/src/modules/users.js
index de28766a..eef87c2c 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -51,6 +51,11 @@ const unblockUser = (store, id) => {
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
}
+const removeUserFromFollowers = (store, id) => {
+ return store.rootState.api.backendInteractor.removeUserFromFollowers({ id })
+ .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+}
+
const muteUser = (store, id) => {
const predictedRelationship = store.state.relationships[id] || { id }
predictedRelationship.muting = true
@@ -321,6 +326,9 @@ const users = {
unblockUser (store, id) {
return unblockUser(store, id)
},
+ removeUserFromFollowers (store, id) {
+ return removeUserFromFollowers(store, id)
+ },
blockUsers (store, ids = []) {
return Promise.all(ids.map(id => blockUser(store, id)))
},