aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.scss12
-rw-r--r--src/_variables.scss1
-rw-r--r--src/boot/after_store.js55
-rw-r--r--src/components/emoji_input/emoji_input.js21
-rw-r--r--src/components/emoji_input/emoji_input.vue5
-rw-r--r--src/components/emoji_picker/emoji_picker.js77
-rw-r--r--src/components/emoji_picker/emoji_picker.scss28
-rw-r--r--src/components/emoji_picker/emoji_picker.vue14
-rw-r--r--src/components/post_status_form/post_status_form.js32
-rw-r--r--src/components/post_status_form/post_status_form.vue7
-rw-r--r--src/components/style_switcher/style_switcher.js3
-rw-r--r--src/components/style_switcher/style_switcher.vue7
-rw-r--r--src/i18n/en.json5
-rw-r--r--src/modules/instance.js61
-rw-r--r--src/modules/users.js2
-rw-r--r--src/services/style_setter/style_setter.js5
16 files changed, 252 insertions, 83 deletions
diff --git a/src/App.scss b/src/App.scss
index 2d10f1e7..310962b8 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -661,6 +661,18 @@ nav {
color: var(--alertErrorPanelText, $fallback--text);
}
}
+
+ &.warning {
+ background-color: $fallback--alertWarning;
+ background-color: var(--alertWarning, $fallback--alertWarning);
+ color: $fallback--text;
+ color: var(--alertWarningText, $fallback--text);
+
+ .panel-heading & {
+ color: $fallback--text;
+ color: var(--alertWarningPanelText, $fallback--text);
+ }
+ }
}
.faint {
diff --git a/src/_variables.scss b/src/_variables.scss
index 150e4fb5..e18101f0 100644
--- a/src/_variables.scss
+++ b/src/_variables.scss
@@ -17,6 +17,7 @@ $fallback--cGreen: #0fa00f;
$fallback--cOrange: orange;
$fallback--alertError: rgba(211,16,20,.5);
+$fallback--alertWarning: rgba(111,111,20,.5);
$fallback--panelRadius: 10px;
$fallback--checkboxRadius: 2px;
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index 490ac4d0..80a55849 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -173,58 +173,6 @@ const getStickers = async ({ store }) => {
}
}
-const getStaticEmoji = async ({ store }) => {
- 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.displayText - b.displayText)
- store.dispatch('setInstanceOption', { name: 'emoji', value: emoji })
- } else {
- throw (res)
- }
- } catch (e) {
- console.warn("Can't load static emoji")
- console.warn(e)
- }
-}
-
-// This is also used to indicate if we have a 'pleroma backend' or not.
-// Somewhat weird, should probably be somewhere else.
-const getCustomEmoji = async ({ store }) => {
- 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 emoji = Object.entries(values).map(([key, value]) => {
- const imageUrl = value.image_url
- return {
- displayText: key,
- imageUrl: imageUrl ? store.state.instance.server + imageUrl : value,
- tags: imageUrl ? value.tags.sort((a, b) => a > b ? 1 : 0) : ['utf'],
- replacement: `:${key}: `
- }
- // 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 : 0)
- store.dispatch('setInstanceOption', { name: 'customEmoji', value: emoji })
- store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: true })
- } else {
- throw (res)
- }
- } catch (e) {
- store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: false })
- console.warn("Can't load custom emojis, maybe not a Pleroma instance?")
- console.warn(e)
- }
-}
-
const getAppSecret = async ({ store }) => {
const { state, commit } = store
const { oauth, instance } = state
@@ -259,6 +207,7 @@ const getNodeInfo = async ({ store }) => {
const software = data.software
store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
+ store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' })
const frontendVersion = window.___pleromafe_commit_hash
store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
@@ -315,8 +264,6 @@ const afterStoreSetup = async ({ store, i18n }) => {
getTOS({ store }),
getInstancePanel({ store }),
getStickers({ store }),
- getStaticEmoji({ store }),
- getCustomEmoji({ store }),
getNodeInfo({ store })
])
diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js
index 366951c0..001a22e9 100644
--- a/src/components/emoji_input/emoji_input.js
+++ b/src/components/emoji_input/emoji_input.js
@@ -165,6 +165,7 @@ const EmojiInput = {
methods: {
triggerShowPicker () {
this.showPicker = true
+ this.$refs.picker.startEmojiLoad()
this.$nextTick(() => {
this.scrollIntoView()
})
@@ -181,6 +182,7 @@ const EmojiInput = {
this.showPicker = !this.showPicker
if (this.showPicker) {
this.scrollIntoView()
+ this.$refs.picker.startEmojiLoad()
}
},
replace (replacement) {
@@ -306,6 +308,16 @@ const EmojiInput = {
} else {
scrollerRef.scrollTop = targetScroll
}
+
+ this.$nextTick(() => {
+ const { offsetHeight } = this.input.elm
+ const { picker } = this.$refs
+ const pickerBottom = picker.$el.getBoundingClientRect().bottom
+ if (pickerBottom > window.innerHeight) {
+ picker.$el.style.top = 'auto'
+ picker.$el.style.bottom = offsetHeight + 'px'
+ }
+ })
},
onTransition (e) {
this.resize()
@@ -419,11 +431,14 @@ const EmojiInput = {
this.caret = selectionStart
},
resize () {
- const { panel } = this.$refs
+ const { panel, picker } = this.$refs
if (!panel) return
const { offsetHeight, offsetTop } = this.input.elm
- this.$refs.panel.style.top = (offsetTop + offsetHeight) + 'px'
- this.$refs.picker.$el.style.top = (offsetTop + offsetHeight) + 'px'
+ const offsetBottom = offsetTop + offsetHeight
+
+ panel.style.top = offsetBottom + 'px'
+ picker.$el.style.top = offsetBottom + 'px'
+ picker.$el.style.bottom = 'auto'
}
}
}
diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue
index 13530e8b..a7215670 100644
--- a/src/components/emoji_input/emoji_input.vue
+++ b/src/components/emoji_input/emoji_input.vue
@@ -2,6 +2,7 @@
<div
v-click-outside="onClickOutside"
class="emoji-input"
+ :class="{ 'with-picker': !hideEmojiButton }"
>
<slot />
<template v-if="enableEmojiPicker">
@@ -63,6 +64,10 @@
flex-direction: column;
position: relative;
+ &.with-picker input {
+ padding-right: 30px;
+ }
+
.emoji-picker-icon {
position: absolute;
top: 0;
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index b1d70176..76d1f26b 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -1,5 +1,10 @@
+import { set } from 'vue'
import Checkbox from '../checkbox/checkbox.vue'
+const LOAD_EMOJI_BY = 50
+const LOAD_EMOJI_INTERVAL = 100
+const LOAD_EMOJI_SANE_AMOUNT = 500
+
const filterByKeyword = (list, keyword = '') => {
return list.filter(x => x.displayText.includes(keyword))
}
@@ -18,7 +23,12 @@ const EmojiPicker = {
activeGroup: 'custom',
showingStickers: false,
groupsScrolledClass: 'scrolled-top',
- keepOpen: false
+ keepOpen: false,
+ customEmojiBuffer: (this.$store.state.instance.customEmoji || [])
+ .slice(0, LOAD_EMOJI_BY),
+ customEmojiTimeout: null,
+ customEmojiCounter: LOAD_EMOJI_BY,
+ customEmojiLoadAllConfirmed: false
}
},
components: {
@@ -58,6 +68,50 @@ const EmojiPicker = {
})
})
},
+ loadEmojiInsane () {
+ this.customEmojiLoadAllConfirmed = true
+ this.continueEmojiLoad()
+ },
+ loadEmoji () {
+ const allLoaded = this.customEmojiBuffer.length === this.filteredEmoji.length
+ const saneLoaded = this.customEmojiBuffer.length >= LOAD_EMOJI_SANE_AMOUNT &&
+ !this.customEmojiLoadAllConfirmed
+
+ if (allLoaded || saneLoaded) {
+ return
+ }
+
+ this.customEmojiBuffer.push(
+ ...this.filteredEmoji.slice(
+ this.customEmojiCounter,
+ this.customEmojiCounter + LOAD_EMOJI_BY
+ )
+ )
+ this.customEmojiTimeout = window.setTimeout(this.loadEmoji, LOAD_EMOJI_INTERVAL)
+ this.customEmojiCounter += LOAD_EMOJI_BY
+ },
+ startEmojiLoad (forceUpdate = false) {
+ const bufferSize = this.customEmojiBuffer.length
+ const bufferPrefilledSane = bufferSize === LOAD_EMOJI_SANE_AMOUNT && !this.customEmojiLoadAllConfirmed
+ const bufferPrefilledAll = bufferSize === this.filteredEmoji.length
+ if (forceUpdate || bufferPrefilledSane || bufferPrefilledAll) {
+ return
+ }
+ if (this.customEmojiTimeout) {
+ window.clearTimeout(this.customEmojiTimeout)
+ }
+
+ set(
+ this,
+ 'customEmojiBuffer',
+ this.filteredEmoji.slice(0, LOAD_EMOJI_BY)
+ )
+ this.customEmojiCounter = LOAD_EMOJI_BY
+ this.customEmojiTimeout = window.setTimeout(this.loadEmoji, LOAD_EMOJI_INTERVAL)
+ },
+ continueEmojiLoad () {
+ this.customEmojiTimeout = window.setTimeout(this.loadEmoji, LOAD_EMOJI_INTERVAL)
+ },
toggleStickers () {
this.showingStickers = !this.showingStickers
},
@@ -73,7 +127,9 @@ const EmojiPicker = {
},
watch: {
keyword () {
+ this.customEmojiLoadAllConfirmed = false
this.scrolledGroup()
+ this.startEmojiLoad(true)
}
},
computed: {
@@ -86,15 +142,30 @@ const EmojiPicker = {
}
return 0
},
+ saneAmount () {
+ // for UI
+ return LOAD_EMOJI_SANE_AMOUNT
+ },
+ filteredEmoji () {
+ return filterByKeyword(
+ this.$store.state.instance.customEmoji || [],
+ this.keyword
+ )
+ },
+ askForSanity () {
+ return this.customEmojiBuffer.length >= LOAD_EMOJI_SANE_AMOUNT &&
+ !this.customEmojiLoadAllConfirmed
+ },
emojis () {
const standardEmojis = this.$store.state.instance.emoji || []
- const customEmojis = this.$store.state.instance.customEmoji || []
+ const customEmojis = this.customEmojiBuffer
+
return [
{
id: 'custom',
text: this.$t('emoji.custom'),
icon: 'icon-smile',
- emojis: filterByKeyword(customEmojis, this.keyword)
+ emojis: customEmojis
},
{
id: 'standard',
diff --git a/src/components/emoji_picker/emoji_picker.scss b/src/components/emoji_picker/emoji_picker.scss
index d99539b0..6608f393 100644
--- a/src/components/emoji_picker/emoji_picker.scss
+++ b/src/components/emoji_picker/emoji_picker.scss
@@ -6,15 +6,25 @@
position: absolute;
right: 0;
left: 0;
- height: 320px;
margin: 0 !important;
z-index: 1;
- .keep-open {
+ .keep-open,
+ .too-many-emoji {
padding: 7px;
line-height: normal;
}
+ .too-many-emoji {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .keep-open-label {
+ padding: 0 7px;
+ display: flex;
+ }
+
.heading {
display: flex;
height: 32px;
@@ -24,7 +34,7 @@
.content {
display: flex;
flex-direction: column;
- flex: 1 1 0;
+ flex: 1 1 auto;
min-height: 0px;
}
@@ -32,12 +42,16 @@
flex-grow: 1;
}
+ .emoji-groups {
+ min-height: 200px;
+ }
+
.additional-tabs {
border-left: 1px solid;
border-left-color: $fallback--icon;
border-left-color: var(--icon, $fallback--icon);
padding-left: 7px;
- flex: 0 0 0;
+ flex: 0 0 auto;
}
.additional-tabs,
@@ -68,7 +82,7 @@
}
.sticker-picker {
- flex: 1 1 0
+ flex: 1 1 auto
}
.stickers,
@@ -76,7 +90,7 @@
&-content {
display: flex;
flex-direction: column;
- flex: 1 1 0;
+ flex: 1 1 auto;
min-height: 0;
&.hidden {
@@ -90,7 +104,7 @@
.emoji {
&-search {
padding: 5px;
- flex: 0 0 0;
+ flex: 0 0 auto;
input {
width: 100%;
diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue
index b974fce9..43da6aa2 100644
--- a/src/components/emoji_picker/emoji_picker.vue
+++ b/src/components/emoji_picker/emoji_picker.vue
@@ -80,6 +80,20 @@
{{ $t('emoji.keep_open') }}
</Checkbox>
</div>
+ <div
+ v-if="askForSanity"
+ class="too-many-emoji"
+ >
+ <div class="alert warning hint">
+ {{ $t('emoji.load_all_hint', { saneAmount } ) }}
+ </div>
+ <button
+ class="btn btn-default"
+ @click.prevent="loadEmojiInsane"
+ >
+ {{ $t('emoji.load_all', { emojiAmount: filteredEmoji.length } ) }}
+ </button>
+ </div>
</div>
<div
v-if="showingStickers"
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index c1d7209e..af6299e4 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -276,11 +276,15 @@ const PostStatusForm = {
return
}
- const rootRef = this.$refs['root']
+ const formRef = this.$refs['form']
+ const bottomRef = this.$refs['bottom']
/* Scroller is either `window` (replies in TL), sidebar (main post form,
* replies in notifs) or mobile post form. Note that getting and setting
* scroll is different for `Window` and `Element`s
*/
+ const bottomBottomPaddingStr = window.getComputedStyle(bottomRef)['padding-bottom']
+ const bottomBottomPadding = Number(bottomBottomPaddingStr.substring(0, bottomBottomPaddingStr.length - 2))
+
const scrollerRef = this.$el.closest('.sidebar-scroller') ||
this.$el.closest('.post-form-modal-view') ||
window
@@ -292,9 +296,6 @@ const PostStatusForm = {
const bottomPadding = Number(bottomPaddingStr.substring(0, bottomPaddingStr.length - 2))
const vertPadding = topPadding + bottomPadding
- const oldHeightStr = target.style.height || ''
- const oldHeight = Number(oldHeightStr.substring(0, oldHeightStr.length - 2))
-
/* Explanation:
*
* https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight
@@ -306,7 +307,7 @@ const PostStatusForm = {
* SHRINK the textarea when there's extra space. To workaround that we set
* height to 'auto' which makes textarea tiny again, so that scrollHeight
* will match text height again. HOWEVER, shrinking textarea can screw with
- * the scroll since there might be not enough padding around root to even
+ * the scroll since there might be not enough padding around form-bottom to even
* warrant a scroll, so it will jump to 0 and refuse to move anywhere,
* so we check current scroll position before shrinking and then restore it
* with needed delta.
@@ -327,16 +328,21 @@ const PostStatusForm = {
target.style.height = `${newHeight}px`
// END content size update
- // We check where the bottom border of root element is, this uses findOffset
+ // We check where the bottom border of form-bottom element is, this uses findOffset
// to find offset relative to scrollable container (scroller)
- const rootBottomBorder = rootRef.offsetHeight + findOffset(rootRef, scrollerRef).top
-
- const textareaSizeChangeDelta = newHeight - oldHeight || 0
- const isBottomObstructed = scrollerBottomBorder < rootBottomBorder
- const rootChangeDelta = rootBottomBorder - scrollerBottomBorder
- const totalDelta = textareaSizeChangeDelta +
- (isBottomObstructed ? rootChangeDelta : 0)
+ const bottomBottomBorder = bottomRef.offsetHeight + findOffset(bottomRef, scrollerRef).top + bottomBottomPadding
+ const isBottomObstructed = scrollerBottomBorder < bottomBottomBorder
+ const isFormBiggerThanScroller = scrollerHeight < formRef.offsetHeight
+ const bottomChangeDelta = bottomBottomBorder - scrollerBottomBorder
+ // The intention is basically this;
+ // Keep form-bottom always visible so that submit button is in view EXCEPT
+ // if form element bigger than scroller and caret isn't at the end, so that
+ // if you scroll up and edit middle of text you won't get scrolled back to bottom
+ const shouldScrollToBottom = isBottomObstructed &&
+ !(isFormBiggerThanScroller &&
+ this.$refs.textarea.selectionStart !== this.$refs.textarea.value.length)
+ const totalDelta = shouldScrollToBottom ? bottomChangeDelta : 0
const targetScroll = currentScroll + totalDelta
if (scrollerRef === window) {
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 237ed725..13e8b0aa 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -1,6 +1,6 @@
<template>
<div
- ref="root"
+ ref="form"
class="post-status-form"
>
<form
@@ -160,7 +160,10 @@
:visible="pollFormVisible"
@update-poll="setPoll"
/>
- <div class="form-bottom">
+ <div
+ ref="bottom"
+ class="form-bottom"
+ >
<div class="form-bottom-left">
<media-upload
ref="mediaUpload"
diff --git a/src/components/style_switcher/style_switcher.js b/src/components/style_switcher/style_switcher.js
index 6e2a1d7b..ebde4475 100644
--- a/src/components/style_switcher/style_switcher.js
+++ b/src/components/style_switcher/style_switcher.js
@@ -74,6 +74,7 @@ export default {
topBarLinkColorLocal: undefined,
alertErrorColorLocal: undefined,
+ alertWarningColorLocal: undefined,
badgeOpacityLocal: undefined,
badgeNotificationColorLocal: undefined,
@@ -147,6 +148,7 @@ export default {
btnText: this.btnTextColorLocal,
alertError: this.alertErrorColorLocal,
+ alertWarning: this.alertWarningColorLocal,
badgeNotification: this.badgeNotificationColorLocal,
faint: this.faintColorLocal,
@@ -230,6 +232,7 @@ export default {
topBar: hex2rgb(colors.topBar),
input: hex2rgb(colors.input),
alertError: hex2rgb(colors.alertError),
+ alertWarning: hex2rgb(colors.alertWarning),
badgeNotification: hex2rgb(colors.badgeNotification)
}
diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue
index 944debab..ad032041 100644
--- a/src/components/style_switcher/style_switcher.vue
+++ b/src/components/style_switcher/style_switcher.vue
@@ -201,6 +201,13 @@
:fallback="previewTheme.colors.alertError"
/>
<ContrastRatio :contrast="previewContrast.alertError" />
+ <ColorInput
+ v-model="alertWarningColorLocal"
+ name="alertWarning"
+ :label="$t('settings.style.advanced_colors.alert_warning')"
+ :fallback="previewTheme.colors.alertWarning"
+ />
+ <ContrastRatio :contrast="previewContrast.alertWarning" />
</div>
<div class="color-item">
<h4>{{ $t('settings.style.advanced_colors.badge') }}</h4>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 7afe7857..8ecb3f3d 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -114,7 +114,9 @@
"search_emoji": "Search for an emoji",
"add_emoji": "Insert emoji",
"custom": "Custom emoji",
- "unicode": "Unicode emoji"
+ "unicode": "Unicode emoji",
+ "load_all_hint": "Loaded first {saneAmount} emoji, loading all emoji may cause performance issues.",
+ "load_all": "Loading all {emojiAmount} emoji"
},
"interactions": {
"favs_repeats": "Repeats and Favorites",
@@ -391,6 +393,7 @@
"_tab_label": "Advanced",
"alert": "Alert background",
"alert_error": "Error",
+ "alert_warning": "Warning",
"badge": "Badge background",
"badge_notification": "Notification",
"panel_header": "Panel header",
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 0c1235ca..7b0e0da4 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -36,7 +36,9 @@ const defaultState = {
// Nasty stuff
pleromaBackend: true,
emoji: [],
+ emojiFetched: false,
customEmoji: [],
+ customEmojiFetched: false,
restrictedNicknames: [],
postFormats: [],
@@ -94,9 +96,68 @@ const instance = {
break
}
},
+ 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.displayText - b.displayText)
+ commit('setInstanceOption', { name: 'emoji', value: emoji })
+ } else {
+ throw (res)
+ }
+ } catch (e) {
+ console.warn("Can't load static emoji")
+ console.warn(e)
+ }
+ },
+
+ 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 emoji = Object.entries(values).map(([key, value]) => {
+ const imageUrl = value.image_url
+ return {
+ displayText: key,
+ imageUrl: imageUrl ? state.server + imageUrl : value,
+ tags: imageUrl ? value.tags.sort((a, b) => a > b ? 1 : 0) : ['utf'],
+ replacement: `:${key}: `
+ }
+ // 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 : 0)
+ commit('setInstanceOption', { name: 'customEmoji', value: emoji })
+ } else {
+ throw (res)
+ }
+ } catch (e) {
+ console.warn("Can't load custom emojis")
+ console.warn(e)
+ }
+ },
+
setTheme ({ commit }, themeName) {
commit('setInstanceOption', { name: 'theme', value: themeName })
return setPreset(themeName, commit)
+ },
+ fetchEmoji ({ dispatch, state }) {
+ if (!state.customEmojiFetched) {
+ state.customEmojiFetched = true
+ dispatch('getCustomEmoji')
+ }
+ if (!state.emojiFetched) {
+ state.emojiFetched = true
+ dispatch('getStaticEmoji')
+ }
}
}
}
diff --git a/src/modules/users.js b/src/modules/users.js
index 6d259dc2..1c9ff5e8 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -453,6 +453,8 @@ const users = {
commit('setCurrentUser', user)
commit('addNewUsers', [user])
+ store.dispatch('fetchEmoji')
+
getNotificationPermission()
.then(permission => commit('setNotificationPermission', permission))
diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js
index 1cf7edc3..eaa495c4 100644
--- a/src/services/style_setter/style_setter.js
+++ b/src/services/style_setter/style_setter.js
@@ -215,6 +215,10 @@ const generateColors = (input) => {
colors.alertErrorText = getTextColor(alphaBlend(colors.alertError, opacity.alert, colors.bg), colors.text)
colors.alertErrorPanelText = getTextColor(alphaBlend(colors.alertError, opacity.alert, colors.panel), colors.panelText)
+ colors.alertWarning = col.alertWarning || Object.assign({}, colors.cOrange)
+ colors.alertWarningText = getTextColor(alphaBlend(colors.alertWarning, opacity.alert, colors.bg), colors.text)
+ colors.alertWarningPanelText = getTextColor(alphaBlend(colors.alertWarning, opacity.alert, colors.panel), colors.panelText)
+
colors.badgeNotification = col.badgeNotification || Object.assign({}, colors.cRed)
colors.badgeNotificationText = contrastRatio(colors.badgeNotification).rgb
@@ -222,6 +226,7 @@ const generateColors = (input) => {
if (typeof v === 'undefined') return
if (k === 'alert') {
colors.alertError.a = v
+ colors.alertWarning.a = v
return
}
if (k === 'faint') {