Merge branch 'develop' into 'tusooa/save-draft'
# Conflicts: # src/boot/routes.js # src/i18n/en.json # src/main.js # src/modules/config.js # src/modules/instance.js
This commit is contained in:
commit
3cda070507
282 changed files with 8443 additions and 1913 deletions
|
|
@ -203,12 +203,13 @@ const api = {
|
|||
tag = false,
|
||||
userId = false,
|
||||
listId = false,
|
||||
statusId = false
|
||||
statusId = false,
|
||||
bookmarkFolderId = false
|
||||
}) {
|
||||
if (store.state.fetchers[timeline]) return
|
||||
|
||||
const fetcher = store.state.backendInteractor.startFetchingTimeline({
|
||||
timeline, store, userId, listId, statusId, tag
|
||||
timeline, store, userId, listId, statusId, bookmarkFolderId, tag
|
||||
})
|
||||
store.commit('addFetcher', { fetcherName: timeline, fetcher })
|
||||
},
|
||||
|
|
@ -272,6 +273,18 @@ const api = {
|
|||
store.commit('removeFetcher', { fetcherName: 'lists', fetcher })
|
||||
},
|
||||
|
||||
// Bookmark folders
|
||||
startFetchingBookmarkFolders (store) {
|
||||
if (store.state.fetchers.bookmarkFolders) return
|
||||
const fetcher = store.state.backendInteractor.startFetchingBookmarkFolders({ store })
|
||||
store.commit('addFetcher', { fetcherName: 'bookmarkFolders', fetcher })
|
||||
},
|
||||
stopFetchingBookmarkFolders (store) {
|
||||
const fetcher = store.state.fetchers.bookmarkFolders
|
||||
if (!fetcher) return
|
||||
store.commit('removeFetcher', { fetcherName: 'bookmarkFolders', fetcher })
|
||||
},
|
||||
|
||||
// Pleroma websocket
|
||||
setWsToken (store, token) {
|
||||
store.commit('setWsToken', token)
|
||||
|
|
|
|||
66
src/modules/bookmark_folders.js
Normal file
66
src/modules/bookmark_folders.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { remove, find } from 'lodash'
|
||||
|
||||
export const defaultState = {
|
||||
allFolders: []
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
setBookmarkFolders (state, value) {
|
||||
state.allFolders = value
|
||||
},
|
||||
setBookmarkFolder (state, { id, name, emoji, emoji_url: emojiUrl }) {
|
||||
const entry = find(state.allFolders, { id })
|
||||
if (!entry) {
|
||||
state.allFolders.push({ id, name, emoji, emoji_url: emojiUrl })
|
||||
} else {
|
||||
entry.name = name
|
||||
entry.emoji = emoji
|
||||
entry.emoji_url = emojiUrl
|
||||
}
|
||||
},
|
||||
deleteBookmarkFolder (state, { folderId }) {
|
||||
remove(state.allFolders, folder => folder.id === folderId)
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
setBookmarkFolders ({ commit }, value) {
|
||||
commit('setBookmarkFolders', value)
|
||||
},
|
||||
createBookmarkFolder ({ rootState, commit }, { name, emoji }) {
|
||||
return rootState.api.backendInteractor.createBookmarkFolder({ name, emoji })
|
||||
.then((folder) => {
|
||||
commit('setBookmarkFolder', folder)
|
||||
return folder
|
||||
})
|
||||
},
|
||||
setBookmarkFolder ({ rootState, commit }, { folderId, name, emoji }) {
|
||||
return rootState.api.backendInteractor.updateBookmarkFolder({ folderId, name, emoji })
|
||||
.then((folder) => {
|
||||
commit('setBookmarkFolder', folder)
|
||||
return folder
|
||||
})
|
||||
},
|
||||
deleteBookmarkFolder ({ rootState, commit }, { folderId }) {
|
||||
rootState.api.backendInteractor.deleteBookmarkFolder({ folderId })
|
||||
commit('deleteBookmarkFolder', { folderId })
|
||||
}
|
||||
}
|
||||
|
||||
export const getters = {
|
||||
findBookmarkFolderName: state => id => {
|
||||
const folder = state.allFolders.find(folder => folder.id === id)
|
||||
|
||||
if (!folder) return
|
||||
return folder.name
|
||||
}
|
||||
}
|
||||
|
||||
const bookmarkFolders = {
|
||||
state: defaultState,
|
||||
mutations,
|
||||
actions,
|
||||
getters
|
||||
}
|
||||
|
||||
export default bookmarkFolders
|
||||
|
|
@ -48,6 +48,10 @@ export const defaultState = {
|
|||
customThemeSource: undefined, // "source", stores original theme data
|
||||
|
||||
// V3
|
||||
style: null,
|
||||
styleCustomData: null,
|
||||
palette: null,
|
||||
paletteCustomData: null,
|
||||
themeDebug: false, // debug mode that uses computed backgrounds instead of real ones to debug contrast functions
|
||||
forceThemeRecompilation: false, // flag that forces recompilation on boot even if cache exists
|
||||
theme3hacks: { // Hacks, user overrides that are independent of theme used
|
||||
|
|
@ -184,6 +188,8 @@ export const defaultState = {
|
|||
ignoreInactionableSeen: undefined, // instance default
|
||||
unsavedPostAction: undefined, // instance default
|
||||
autoSaveDraft: undefined // instance default
|
||||
useAbsoluteTimeFormat: undefined, // instance default
|
||||
absoluteTimeFormatMinAge: undefined // instance default
|
||||
}
|
||||
|
||||
// caching the instance default properties
|
||||
|
|
@ -304,7 +310,7 @@ const config = {
|
|||
applyConfig(state)
|
||||
}
|
||||
if (name.startsWith('theme3hacks')) {
|
||||
dispatch('setTheme', { recompile: true })
|
||||
dispatch('applyTheme', { recompile: true })
|
||||
}
|
||||
switch (name) {
|
||||
case 'theme':
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ const defaultState = {
|
|||
registrationOpen: true,
|
||||
server: 'http://localhost:4040/',
|
||||
textlimit: 5000,
|
||||
themesIndex: undefined,
|
||||
stylesIndex: undefined,
|
||||
palettesIndex: undefined,
|
||||
themeData: undefined, // used for theme editor v2
|
||||
vapidPublicKey: undefined,
|
||||
|
||||
|
|
@ -96,6 +99,8 @@ const defaultState = {
|
|||
sidebarRight: false,
|
||||
subjectLineBehavior: 'email',
|
||||
theme: 'pleroma-dark',
|
||||
palette: null,
|
||||
style: null,
|
||||
emojiReactionsScale: 0.5,
|
||||
textSize: '14px',
|
||||
emojiSize: '2.2rem',
|
||||
|
|
@ -121,6 +126,8 @@ const defaultState = {
|
|||
ignoreInactionableSeen: false,
|
||||
unsavedPostAction: 'confirm',
|
||||
autoSaveDraft: false,
|
||||
useAbsoluteTimeFormat: false,
|
||||
absoluteTimeFormatMinAge: '0d',
|
||||
|
||||
// Nasty stuff
|
||||
customEmoji: [],
|
||||
|
|
@ -140,6 +147,7 @@ const defaultState = {
|
|||
shoutAvailable: false,
|
||||
pleromaChatMessagesAvailable: false,
|
||||
pleromaCustomEmojiReactionsAvailable: false,
|
||||
pleromaBookmarkFoldersAvailable: false,
|
||||
gopherAvailable: false,
|
||||
mediaProxyAvailable: false,
|
||||
suggestionsEnabled: false,
|
||||
|
|
@ -153,6 +161,7 @@ const defaultState = {
|
|||
|
||||
// Version Information
|
||||
backendVersion: '',
|
||||
backendRepository: '',
|
||||
frontendVersion: '',
|
||||
|
||||
pollsAvailable: false,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,23 @@
|
|||
import { getPreset, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js'
|
||||
import { getResourcesIndex, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js'
|
||||
import { CURRENT_VERSION, generatePreset } from 'src/services/theme_data/theme_data.service.js'
|
||||
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
||||
import { deserialize } from '../services/theme_data/iss_deserializer.js'
|
||||
|
||||
// helper for debugging
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
|
||||
|
||||
const defaultState = {
|
||||
localFonts: null,
|
||||
themeApplied: false,
|
||||
themeVersion: 'v3',
|
||||
styleNameUsed: null,
|
||||
styleDataUsed: null,
|
||||
useStylePalette: false, // hack for applying styles from appearance tab
|
||||
paletteNameUsed: null,
|
||||
paletteDataUsed: null,
|
||||
themeNameUsed: null,
|
||||
themeDataUsed: null,
|
||||
temporaryChangesTimeoutId: null, // used for temporary options that revert after a timeout
|
||||
temporaryChangesConfirm: () => {}, // used for applying temporary options
|
||||
temporaryChangesRevert: () => {}, // used for reverting temporary options
|
||||
|
|
@ -212,142 +225,456 @@ const interfaceMod = {
|
|||
setLastTimeline ({ commit }, value) {
|
||||
commit('setLastTimeline', value)
|
||||
},
|
||||
setTheme ({ commit, rootState }, { themeName, themeData, recompile, saveData } = {}) {
|
||||
async fetchPalettesIndex ({ commit, state }) {
|
||||
try {
|
||||
const value = await getResourcesIndex('/static/palettes/index.json')
|
||||
commit('setInstanceOption', { name: 'palettesIndex', value })
|
||||
return value
|
||||
} catch (e) {
|
||||
console.error('Could not fetch palettes index', e)
|
||||
commit('setInstanceOption', { name: 'palettesIndex', value: { _error: e } })
|
||||
return Promise.resolve({})
|
||||
}
|
||||
},
|
||||
setPalette ({ dispatch, commit }, value) {
|
||||
dispatch('resetThemeV3Palette')
|
||||
dispatch('resetThemeV2')
|
||||
|
||||
commit('setOption', { name: 'palette', value })
|
||||
|
||||
dispatch('applyTheme', { recompile: true })
|
||||
},
|
||||
setPaletteCustom ({ dispatch, commit }, value) {
|
||||
dispatch('resetThemeV3Palette')
|
||||
dispatch('resetThemeV2')
|
||||
|
||||
commit('setOption', { name: 'paletteCustomData', value })
|
||||
|
||||
dispatch('applyTheme', { recompile: true })
|
||||
},
|
||||
async fetchStylesIndex ({ commit, state }) {
|
||||
try {
|
||||
const value = await getResourcesIndex(
|
||||
'/static/styles/index.json',
|
||||
deserialize
|
||||
)
|
||||
commit('setInstanceOption', { name: 'stylesIndex', value })
|
||||
return value
|
||||
} catch (e) {
|
||||
console.error('Could not fetch styles index', e)
|
||||
commit('setInstanceOption', { name: 'stylesIndex', value: { _error: e } })
|
||||
return Promise.resolve({})
|
||||
}
|
||||
},
|
||||
setStyle ({ dispatch, commit, state }, value) {
|
||||
dispatch('resetThemeV3')
|
||||
dispatch('resetThemeV2')
|
||||
dispatch('resetThemeV3Palette')
|
||||
|
||||
commit('setOption', { name: 'style', value })
|
||||
state.useStylePalette = true
|
||||
|
||||
dispatch('applyTheme', { recompile: true }).then(() => {
|
||||
state.useStylePalette = false
|
||||
})
|
||||
},
|
||||
setStyleCustom ({ dispatch, commit, state }, value) {
|
||||
dispatch('resetThemeV3')
|
||||
dispatch('resetThemeV2')
|
||||
dispatch('resetThemeV3Palette')
|
||||
|
||||
commit('setOption', { name: 'styleCustomData', value })
|
||||
|
||||
state.useStylePalette = true
|
||||
dispatch('applyTheme', { recompile: true }).then(() => {
|
||||
state.useStylePalette = false
|
||||
})
|
||||
},
|
||||
async fetchThemesIndex ({ commit, state }) {
|
||||
try {
|
||||
const value = await getResourcesIndex('/static/styles.json')
|
||||
commit('setInstanceOption', { name: 'themesIndex', value })
|
||||
return value
|
||||
} catch (e) {
|
||||
console.error('Could not fetch themes index', e)
|
||||
commit('setInstanceOption', { name: 'themesIndex', value: { _error: e } })
|
||||
return Promise.resolve({})
|
||||
}
|
||||
},
|
||||
setTheme ({ dispatch, commit }, value) {
|
||||
dispatch('resetThemeV3')
|
||||
dispatch('resetThemeV3Palette')
|
||||
dispatch('resetThemeV2')
|
||||
|
||||
commit('setOption', { name: 'theme', value })
|
||||
|
||||
dispatch('applyTheme', { recompile: true })
|
||||
},
|
||||
setThemeCustom ({ dispatch, commit }, value) {
|
||||
dispatch('resetThemeV3')
|
||||
dispatch('resetThemeV3Palette')
|
||||
dispatch('resetThemeV2')
|
||||
|
||||
commit('setOption', { name: 'customTheme', value })
|
||||
commit('setOption', { name: 'customThemeSource', value })
|
||||
|
||||
dispatch('applyTheme', { recompile: true })
|
||||
},
|
||||
resetThemeV3 ({ dispatch, commit }) {
|
||||
commit('setOption', { name: 'style', value: null })
|
||||
commit('setOption', { name: 'styleCustomData', value: null })
|
||||
},
|
||||
resetThemeV3Palette ({ dispatch, commit }) {
|
||||
commit('setOption', { name: 'palette', value: null })
|
||||
commit('setOption', { name: 'paletteCustomData', value: null })
|
||||
},
|
||||
resetThemeV2 ({ dispatch, commit }) {
|
||||
commit('setOption', { name: 'theme', value: null })
|
||||
commit('setOption', { name: 'customTheme', value: null })
|
||||
commit('setOption', { name: 'customThemeSource', value: null })
|
||||
},
|
||||
async getThemeData ({ dispatch, commit, rootState, state }) {
|
||||
const getData = async (resource, index, customData, name) => {
|
||||
const capitalizedResource = resource[0].toUpperCase() + resource.slice(1)
|
||||
const result = {}
|
||||
|
||||
if (customData) {
|
||||
result.nameUsed = 'custom' // custom data overrides name
|
||||
result.dataUsed = customData
|
||||
} else {
|
||||
result.nameUsed = name
|
||||
|
||||
if (result.nameUsed == null) {
|
||||
result.dataUsed = null
|
||||
return result
|
||||
}
|
||||
|
||||
let fetchFunc = index[result.nameUsed]
|
||||
// Fallbacks
|
||||
if (!fetchFunc) {
|
||||
if (resource === 'style' || resource === 'palette') {
|
||||
return result
|
||||
}
|
||||
const newName = Object.keys(index)[0]
|
||||
fetchFunc = index[newName]
|
||||
console.warn(`${capitalizedResource} with id '${state.styleNameUsed}' not found, trying back to '${newName}'`)
|
||||
if (!fetchFunc) {
|
||||
console.warn(`${capitalizedResource} doesn't have a fallback, defaulting to stock.`)
|
||||
fetchFunc = () => Promise.resolve(null)
|
||||
}
|
||||
}
|
||||
result.dataUsed = await fetchFunc()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const {
|
||||
theme: instanceThemeName
|
||||
style: instanceStyleName,
|
||||
palette: instancePaletteName
|
||||
} = rootState.instance
|
||||
|
||||
let {
|
||||
theme: instanceThemeV2Name,
|
||||
themesIndex,
|
||||
stylesIndex,
|
||||
palettesIndex
|
||||
} = rootState.instance
|
||||
|
||||
const {
|
||||
theme: userThemeName,
|
||||
customTheme: userThemeSnapshot,
|
||||
customThemeSource: userThemeSource,
|
||||
style: userStyleName,
|
||||
styleCustomData: userStyleCustomData,
|
||||
palette: userPaletteName,
|
||||
paletteCustomData: userPaletteCustomData
|
||||
} = rootState.config
|
||||
|
||||
let {
|
||||
theme: userThemeV2Name,
|
||||
customTheme: userThemeV2Snapshot,
|
||||
customThemeSource: userThemeV2Source
|
||||
} = rootState.config
|
||||
|
||||
let majorVersionUsed
|
||||
|
||||
console.debug(
|
||||
`User V3 palette: ${userPaletteName}, style: ${userStyleName} , custom: ${!!userStyleCustomData}`
|
||||
)
|
||||
console.debug(
|
||||
`User V2 name: ${userThemeV2Name}, source: ${!!userThemeV2Source}, snapshot: ${!!userThemeV2Snapshot}`
|
||||
)
|
||||
|
||||
console.debug(`Instance V3 palette: ${instancePaletteName}, style: ${instanceStyleName}`)
|
||||
console.debug('Instance V2 theme: ' + instanceThemeV2Name)
|
||||
|
||||
if (userPaletteName || userPaletteCustomData ||
|
||||
userStyleName || userStyleCustomData ||
|
||||
(
|
||||
// User V2 overrides instance V3
|
||||
(instancePaletteName ||
|
||||
instanceStyleName) &&
|
||||
instanceThemeV2Name == null &&
|
||||
userThemeV2Name == null
|
||||
)
|
||||
) {
|
||||
// Palette and/or style overrides V2 themes
|
||||
instanceThemeV2Name = null
|
||||
userThemeV2Name = null
|
||||
userThemeV2Source = null
|
||||
userThemeV2Snapshot = null
|
||||
|
||||
majorVersionUsed = 'v3'
|
||||
} else if (
|
||||
(userThemeV2Name ||
|
||||
userThemeV2Snapshot ||
|
||||
userThemeV2Source ||
|
||||
instanceThemeV2Name)
|
||||
) {
|
||||
majorVersionUsed = 'v2'
|
||||
} else {
|
||||
// if all fails fallback to v3
|
||||
majorVersionUsed = 'v3'
|
||||
}
|
||||
|
||||
if (majorVersionUsed === 'v3') {
|
||||
const result = await Promise.all([
|
||||
dispatch('fetchPalettesIndex'),
|
||||
dispatch('fetchStylesIndex')
|
||||
])
|
||||
|
||||
palettesIndex = result[0]
|
||||
stylesIndex = result[1]
|
||||
} else {
|
||||
// Promise.all just to be uniform with v3
|
||||
const result = await Promise.all([
|
||||
dispatch('fetchThemesIndex')
|
||||
])
|
||||
|
||||
themesIndex = result[0]
|
||||
}
|
||||
|
||||
state.themeVersion = majorVersionUsed
|
||||
|
||||
console.debug('Version used', majorVersionUsed)
|
||||
|
||||
if (majorVersionUsed === 'v3') {
|
||||
state.themeDataUsed = null
|
||||
state.themeNameUsed = null
|
||||
|
||||
const style = await getData(
|
||||
'style',
|
||||
stylesIndex,
|
||||
userStyleCustomData,
|
||||
userStyleName || instanceStyleName
|
||||
)
|
||||
state.styleNameUsed = style.nameUsed
|
||||
state.styleDataUsed = style.dataUsed
|
||||
|
||||
let firstStylePaletteName = null
|
||||
style
|
||||
.dataUsed
|
||||
?.filter(x => x.component === '@palette')
|
||||
.map(x => {
|
||||
const cleanDirectives = Object.fromEntries(
|
||||
Object
|
||||
.entries(x.directives)
|
||||
.filter(([k, v]) => k)
|
||||
)
|
||||
|
||||
return { name: x.variant, ...cleanDirectives }
|
||||
})
|
||||
.forEach(palette => {
|
||||
const key = 'style.' + palette.name.toLowerCase().replace(/ /g, '_')
|
||||
if (!firstStylePaletteName) firstStylePaletteName = key
|
||||
palettesIndex[key] = () => Promise.resolve(palette)
|
||||
})
|
||||
|
||||
const palette = await getData(
|
||||
'palette',
|
||||
palettesIndex,
|
||||
userPaletteCustomData,
|
||||
state.useStylePalette ? firstStylePaletteName : (userPaletteName || instancePaletteName)
|
||||
)
|
||||
|
||||
if (state.useStylePalette) {
|
||||
commit('setOption', { name: 'palette', value: firstStylePaletteName })
|
||||
}
|
||||
|
||||
state.paletteNameUsed = palette.nameUsed
|
||||
state.paletteDataUsed = palette.dataUsed
|
||||
|
||||
if (state.paletteDataUsed) {
|
||||
state.paletteDataUsed.link = state.paletteDataUsed.link || state.paletteDataUsed.accent
|
||||
state.paletteDataUsed.accent = state.paletteDataUsed.accent || state.paletteDataUsed.link
|
||||
}
|
||||
if (Array.isArray(state.paletteDataUsed)) {
|
||||
const [
|
||||
name,
|
||||
bg,
|
||||
fg,
|
||||
text,
|
||||
link,
|
||||
cRed = '#FF0000',
|
||||
cGreen = '#00FF00',
|
||||
cBlue = '#0000FF',
|
||||
cOrange = '#E3FF00'
|
||||
] = palette.dataUsed
|
||||
state.paletteDataUsed = {
|
||||
name,
|
||||
bg,
|
||||
fg,
|
||||
text,
|
||||
link,
|
||||
accent: link,
|
||||
cRed,
|
||||
cBlue,
|
||||
cGreen,
|
||||
cOrange
|
||||
}
|
||||
}
|
||||
console.debug('Palette data used', palette.dataUsed)
|
||||
} else {
|
||||
state.styleNameUsed = null
|
||||
state.styleDataUsed = null
|
||||
state.paletteNameUsed = null
|
||||
state.paletteDataUsed = null
|
||||
|
||||
const theme = await getData(
|
||||
'theme',
|
||||
themesIndex,
|
||||
userThemeV2Source || userThemeV2Snapshot,
|
||||
userThemeV2Name || instanceThemeV2Name
|
||||
)
|
||||
state.themeNameUsed = theme.nameUsed
|
||||
state.themeDataUsed = theme.dataUsed
|
||||
}
|
||||
},
|
||||
async applyTheme (
|
||||
{ dispatch, commit, rootState, state },
|
||||
{ recompile = false } = {}
|
||||
) {
|
||||
const {
|
||||
forceThemeRecompilation,
|
||||
themeDebug,
|
||||
theme3hacks
|
||||
} = rootState.config
|
||||
|
||||
const actualThemeName = userThemeName || instanceThemeName
|
||||
|
||||
const forceRecompile = forceThemeRecompilation || recompile
|
||||
|
||||
let promise = null
|
||||
|
||||
if (themeData) {
|
||||
promise = Promise.resolve(normalizeThemeData(themeData))
|
||||
} else if (themeName) {
|
||||
promise = getPreset(themeName).then(themeData => normalizeThemeData(themeData))
|
||||
} else if (userThemeSource || userThemeSnapshot) {
|
||||
promise = Promise.resolve(normalizeThemeData({
|
||||
_pleroma_theme_version: 2,
|
||||
theme: userThemeSnapshot,
|
||||
source: userThemeSource
|
||||
}))
|
||||
} else if (actualThemeName && actualThemeName !== 'custom') {
|
||||
promise = getPreset(actualThemeName).then(themeData => {
|
||||
const realThemeData = normalizeThemeData(themeData)
|
||||
if (actualThemeName === instanceThemeName) {
|
||||
// This sole line is the reason why this whole block is above the recompilation check
|
||||
commit('setInstanceOption', { name: 'themeData', value: { theme: realThemeData } })
|
||||
}
|
||||
return realThemeData
|
||||
})
|
||||
} else {
|
||||
throw new Error('Cannot load any theme!')
|
||||
}
|
||||
|
||||
// If we're not not forced to recompile try using
|
||||
// cache (tryLoadCache return true if load successful)
|
||||
if (!forceRecompile && !themeDebug && tryLoadCache()) {
|
||||
commit('setThemeApplied')
|
||||
return
|
||||
|
||||
const forceRecompile = forceThemeRecompilation || recompile
|
||||
if (!forceRecompile && !themeDebug && await tryLoadCache()) {
|
||||
return commit('setThemeApplied')
|
||||
}
|
||||
window.splashUpdate('splash.theme')
|
||||
await dispatch('getThemeData')
|
||||
|
||||
promise
|
||||
.then(realThemeData => {
|
||||
const theme2ruleset = convertTheme2To3(realThemeData)
|
||||
|
||||
if (saveData) {
|
||||
commit('setOption', { name: 'theme', value: themeName || actualThemeName })
|
||||
commit('setOption', { name: 'customTheme', value: realThemeData })
|
||||
commit('setOption', { name: 'customThemeSource', value: realThemeData })
|
||||
try {
|
||||
const paletteIss = (() => {
|
||||
if (!state.paletteDataUsed) return null
|
||||
const result = {
|
||||
component: 'Root',
|
||||
directives: {}
|
||||
}
|
||||
const hacks = []
|
||||
|
||||
Object.entries(theme3hacks).forEach(([key, value]) => {
|
||||
switch (key) {
|
||||
case 'fonts': {
|
||||
Object.entries(theme3hacks.fonts).forEach(([fontKey, font]) => {
|
||||
if (!font?.family) return
|
||||
switch (fontKey) {
|
||||
case 'interface':
|
||||
hacks.push({
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--font': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
case 'input':
|
||||
hacks.push({
|
||||
component: 'Input',
|
||||
directives: {
|
||||
'--font': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
case 'post':
|
||||
hacks.push({
|
||||
component: 'RichContent',
|
||||
directives: {
|
||||
'--font': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
case 'monospace':
|
||||
hacks.push({
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--monoFont': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
})
|
||||
break
|
||||
Object
|
||||
.entries(state.paletteDataUsed)
|
||||
.filter(([k]) => k !== 'name')
|
||||
.forEach(([k, v]) => {
|
||||
let issRootDirectiveName
|
||||
switch (k) {
|
||||
case 'background':
|
||||
issRootDirectiveName = 'bg'
|
||||
break
|
||||
case 'foreground':
|
||||
issRootDirectiveName = 'fg'
|
||||
break
|
||||
default:
|
||||
issRootDirectiveName = k
|
||||
}
|
||||
case 'underlay': {
|
||||
if (value !== 'none') {
|
||||
const newRule = {
|
||||
component: 'Underlay',
|
||||
directives: {}
|
||||
}
|
||||
if (value === 'opaque') {
|
||||
newRule.directives.opacity = 1
|
||||
newRule.directives.background = '--wallpaper'
|
||||
}
|
||||
if (value === 'transparent') {
|
||||
newRule.directives.opacity = 0
|
||||
}
|
||||
hacks.push(newRule)
|
||||
result.directives['--' + issRootDirectiveName] = 'color | ' + v
|
||||
})
|
||||
return result
|
||||
})()
|
||||
|
||||
const theme2ruleset = state.themeDataUsed && convertTheme2To3(normalizeThemeData(state.themeDataUsed))
|
||||
const hacks = []
|
||||
|
||||
Object.entries(theme3hacks).forEach(([key, value]) => {
|
||||
switch (key) {
|
||||
case 'fonts': {
|
||||
Object.entries(theme3hacks.fonts).forEach(([fontKey, font]) => {
|
||||
if (!font?.family) return
|
||||
switch (fontKey) {
|
||||
case 'interface':
|
||||
hacks.push({
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--font': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
case 'input':
|
||||
hacks.push({
|
||||
component: 'Input',
|
||||
directives: {
|
||||
'--font': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
case 'post':
|
||||
hacks.push({
|
||||
component: 'RichContent',
|
||||
directives: {
|
||||
'--font': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
case 'monospace':
|
||||
hacks.push({
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--monoFont': 'generic | ' + font.family
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
const ruleset = [
|
||||
...theme2ruleset,
|
||||
...hacks
|
||||
]
|
||||
|
||||
applyTheme(
|
||||
ruleset,
|
||||
() => commit('setThemeApplied'),
|
||||
themeDebug
|
||||
)
|
||||
case 'underlay': {
|
||||
if (value !== 'none') {
|
||||
const newRule = {
|
||||
component: 'Underlay',
|
||||
directives: {}
|
||||
}
|
||||
if (value === 'opaque') {
|
||||
newRule.directives.opacity = 1
|
||||
newRule.directives.background = '--wallpaper'
|
||||
}
|
||||
if (value === 'transparent') {
|
||||
newRule.directives.opacity = 0
|
||||
}
|
||||
hacks.push(newRule)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return promise
|
||||
const rulesetArray = [
|
||||
theme2ruleset,
|
||||
state.styleDataUsed,
|
||||
paletteIss,
|
||||
hacks
|
||||
].filter(x => x)
|
||||
|
||||
return applyTheme(
|
||||
rulesetArray.flat(),
|
||||
() => commit('setThemeApplied'),
|
||||
() => {},
|
||||
themeDebug
|
||||
)
|
||||
} catch (e) {
|
||||
window.splashError(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -355,19 +682,6 @@ const interfaceMod = {
|
|||
export default interfaceMod
|
||||
|
||||
export const normalizeThemeData = (input) => {
|
||||
if (Array.isArray(input)) {
|
||||
const themeData = { colors: {} }
|
||||
themeData.colors.bg = input[1]
|
||||
themeData.colors.fg = input[2]
|
||||
themeData.colors.text = input[3]
|
||||
themeData.colors.link = input[4]
|
||||
themeData.colors.cRed = input[5]
|
||||
themeData.colors.cGreen = input[6]
|
||||
themeData.colors.cBlue = input[7]
|
||||
themeData.colors.cOrange = input[8]
|
||||
return generatePreset(themeData).theme
|
||||
}
|
||||
|
||||
let themeData, themeSource
|
||||
|
||||
if (input.themeFileVerison === 1) {
|
||||
|
|
@ -381,7 +695,10 @@ export const normalizeThemeData = (input) => {
|
|||
// We got passed a full theme file
|
||||
themeData = input.theme
|
||||
themeSource = input.source
|
||||
} else if (Object.prototype.hasOwnProperty.call(input, 'themeEngineVersion')) {
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(input, 'themeEngineVersion') ||
|
||||
Object.prototype.hasOwnProperty.call(input, 'colors')
|
||||
) {
|
||||
// We got passed a source/snapshot
|
||||
themeData = input
|
||||
themeSource = input
|
||||
|
|
|
|||
|
|
@ -385,10 +385,12 @@ export const mutations = {
|
|||
setBookmarked (state, { status, value }) {
|
||||
const newStatus = state.allStatusesObject[status.id]
|
||||
newStatus.bookmarked = value
|
||||
newStatus.bookmark_folder_id = status.bookmark_folder_id
|
||||
},
|
||||
setBookmarkedConfirm (state, { status }) {
|
||||
const newStatus = state.allStatusesObject[status.id]
|
||||
newStatus.bookmarked = status.bookmarked
|
||||
if (status.pleroma) newStatus.bookmark_folder_id = status.pleroma.bookmark_folder
|
||||
},
|
||||
setDeleted (state, { status }) {
|
||||
const newStatus = state.allStatusesObject[status.id]
|
||||
|
|
@ -569,7 +571,7 @@ const statuses = {
|
|||
},
|
||||
bookmark ({ rootState, commit }, status) {
|
||||
commit('setBookmarked', { status, value: true })
|
||||
rootState.api.backendInteractor.bookmarkStatus({ id: status.id })
|
||||
rootState.api.backendInteractor.bookmarkStatus({ id: status.id, folder_id: status.bookmark_folder_id })
|
||||
.then(status => {
|
||||
commit('setBookmarkedConfirm', { status })
|
||||
})
|
||||
|
|
|
|||
|
|
@ -452,11 +452,11 @@ const users = {
|
|||
commit('clearFollowers', userId)
|
||||
},
|
||||
subscribeUser ({ rootState, commit }, id) {
|
||||
return rootState.api.backendInteractor.subscribeUser({ id })
|
||||
return rootState.api.backendInteractor.followUser({ id, notify: true })
|
||||
.then((relationship) => commit('updateUserRelationship', [relationship]))
|
||||
},
|
||||
unsubscribeUser ({ rootState, commit }, id) {
|
||||
return rootState.api.backendInteractor.unsubscribeUser({ id })
|
||||
return rootState.api.backendInteractor.followUser({ id, notify: false })
|
||||
.then((relationship) => commit('updateUserRelationship', [relationship]))
|
||||
},
|
||||
toggleActivationStatus ({ rootState, commit }, { user }) {
|
||||
|
|
@ -579,6 +579,7 @@ const users = {
|
|||
store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken()))
|
||||
store.dispatch('stopFetchingNotifications')
|
||||
store.dispatch('stopFetchingLists')
|
||||
store.dispatch('stopFetchingBookmarkFolders')
|
||||
store.dispatch('stopFetchingFollowRequests')
|
||||
store.commit('clearNotifications')
|
||||
store.commit('resetStatuses')
|
||||
|
|
@ -635,6 +636,7 @@ const users = {
|
|||
}
|
||||
|
||||
dispatch('startFetchingLists')
|
||||
dispatch('startFetchingBookmarkFolders')
|
||||
|
||||
if (user.locked) {
|
||||
dispatch('startFetchingFollowRequests')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue