...
 
Commits (70)
......@@ -12,7 +12,7 @@ import MobilePostStatusButton from './components/mobile_post_status_button/mobil
import MobileNav from './components/mobile_nav/mobile_nav.vue'
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
import { windowWidth } from './services/window_utils/window_utils'
import { windowWidth, windowHeight } from './services/window_utils/window_utils'
export default {
name: 'app',
......@@ -120,10 +120,21 @@ export default {
},
updateMobileState () {
const mobileLayout = windowWidth() <= 800
const layoutHeight = windowHeight()
const changed = mobileLayout !== this.isMobileLayout
if (changed) {
this.$store.dispatch('setMobileLayout', mobileLayout)
}
this.$store.dispatch('setLayoutHeight', layoutHeight)
}
},
watch: {
'$route' (to, from) {
if ((to.name === 'chat' && from.name === 'chats') || (to.name === 'chats' && from.name === 'chat')) {
this.transitionName = 'none'
} else {
this.transitionName = 'fade'
}
}
},
watch: {
......
......@@ -110,6 +110,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
copyInstanceOption('alwaysShowSubjectInput')
copyInstanceOption('showFeaturesPanel')
copyInstanceOption('hideSitename')
copyInstanceOption('sidebarRight')
return store.dispatch('setTheme', config['theme'])
}
......
This diff is collapsed.
......@@ -44,6 +44,20 @@
position: -webkit-sticky;
position: sticky;
.direct-conversation-title {
display: flex;
a {
display: flex;
align-items: center;
}
}
.go-back-button-wrapper {
display: flex;
width: 100%;
}
.button-icon {
cursor: pointer;
display: flex;
......@@ -53,7 +67,7 @@
.go-back-button {
cursor: pointer;
margin-right: 0.7em;
margin-right: 1.2em;
i {
color: $fallback--link;
......@@ -92,6 +106,10 @@
position: -webkit-sticky;
position: sticky;
bottom: 0px;
textarea {
outline: none
}
}
}
}
......
......@@ -10,36 +10,21 @@
ref="header"
class="panel-heading direct-conversation-view-heading mobile-hidden"
>
<!-- <a
class="go-back-button"
@click="goBack"
> -->
<i
class="button-icon icon-left-open"
@click="goBack"
/>
<!-- </a> -->
<div class="title text-center">
<ChatTitle
:users="chatParticipants"
:fallback-user="currentUser"
:with-avatar="true"
<div class="go-back-button-wrapper">
<i
class="button-icon icon-left-open go-back-button"
@click="goBack"
/>
<div class="title text-center">
<ChatTitle
:users="chatParticipants"
:fallback-user="currentUser"
:with-avatar="true"
/>
</div>
</div>
<div style="">
<!-- <ChatAvatar
:users="chatParticipants"
:fallback-user="currentUser"
width="23px"
height="23px"
/> -->
<!-- <a
class=""
style="margin-right: 0.3em;"
@click="goBack"
> -->
<div style="visibility: hidden">
<i class="button-icon icon-info-circled" />
<!-- </a> -->
</div>
</div>
<template>
......@@ -81,10 +66,11 @@
:disable-notice="true"
:disable-polls="true"
:poster="poster"
:preserve-focus="true"
:polls-available="false"
:auto-focus="true"
:submit-on-enter="!isMobileLayout"
:preserve-focus="!isMobileLayout"
:auto-focus="!isMobileLayout"
:placeholder="formPlaceholder"
:file-limit="1"
max-height="160"
@resize="handleResize"
@posted="onPosted"
......
const ChatLayout = {
methods: {
setChatLayout () {
let body = document.querySelector('body')
if (body) {
body.style.overscrollBehavior = 'none'
}
if (this.isMobileLayout) {
this.setMobileChatLayout()
}
},
unsetChatLayout () {
this.unsetMobileChatLayout()
let body = document.querySelector('body')
if (body) {
body.style.overscrollBehavior = 'unset'
}
},
setMobileChatLayout () {
// This is a hacky way to adjust the global layout to the mobile chat (without modifying the rest of the app).
// This layout prevents empty spaces from being visible at the bottom
// of the chat on iOS Safari (`safe-area-inset`) when
// - the on-screen keyboard appears and the user starts typing
// - the user selects the text inside the input area
// - the user selects and deletes the text that is multiple lines long
// TODO: unify the chat layout with the global layout.
let html = document.querySelector('html')
if (html) {
html.style.overflow = 'hidden'
html.style.height = '100%'
}
let body = document.querySelector('body')
if (body) {
body.style.height = '100%'
}
let app = document.getElementById('app')
if (app) {
app.style.height = '100%'
app.style.overflow = 'hidden'
app.style.minHeight = 'auto'
}
let appBgWrapper = window.document.getElementById('app_bg_wrapper')
if (appBgWrapper) {
appBgWrapper.style.overflow = 'hidden'
}
let main = document.getElementsByClassName('main')[0]
if (main) {
main.style.overflow = 'hidden'
main.style.height = '100%'
}
let content = document.getElementById('content')
if (content) {
content.style.paddingTop = '0'
content.style.height = '100%'
content.style.overflow = 'visible'
}
this.$nextTick(() => {
this.updateSize()
})
},
unsetMobileChatLayout () {
let html = document.querySelector('html')
if (html) {
html.style.overflow = 'visible'
html.style.height = 'unset'
}
let body = document.querySelector('body')
if (body) {
body.style.height = 'unset'
}
let app = document.getElementById('app')
if (app) {
app.style.height = '100%'
app.style.overflow = 'visible'
app.style.minHeight = '100vh'
}
let appBgWrapper = document.getElementById('app_bg_wrapper')
if (appBgWrapper) {
appBgWrapper.style.overflow = 'visible'
}
let main = document.getElementsByClassName('main')[0]
if (main) {
main.style.overflow = 'visible'
main.style.height = 'unset'
}
let content = document.getElementById('content')
if (content) {
content.style.paddingTop = '60px'
content.style.height = 'unset'
content.style.overflow = 'unset'
}
}
}
}
export default ChatLayout
......@@ -162,6 +162,11 @@ const EmojiInput = {
input.elm.removeEventListener('input', this.onInput)
}
},
watch: {
showSuggestions: function (newValue) {
this.$emit('shown', newValue)
}
},
methods: {
triggerShowPicker () {
this.showPicker = true
......
......@@ -62,7 +62,8 @@ const mediaUpload = {
}
},
props: [
'dropFiles'
'dropFiles',
'disabled'
],
watch: {
'dropFiles': function (fileInfos) {
......
<template>
<div
class="media-upload"
:class="{ disabled: disabled }"
@drop.prevent
@dragover.prevent="fileDrag"
@drop="fileDrop"
......@@ -19,6 +20,7 @@
/>
<input
v-if="uploadReady"
:disabled="disabled"
type="file"
style="position: fixed; top: -100em"
multiple="true"
......@@ -31,7 +33,22 @@
<script src="./media_upload.js" ></script>
<style lang="scss">
@import '../../_variables.scss';
.media-upload {
&.disabled {
.new-icon {
cursor: not-allowed;
}
&:hover {
i, label {
color: $fallback--faint;
color: var(--faint, $fallback--faint);
}
}
}
.label {
display: inline-block;
}
......
......@@ -30,7 +30,10 @@ const MobileNav = {
return this.unseenNotifications.length
},
hideSitename () { return this.$store.state.instance.hideSitename },
sitename () { return this.$store.state.instance.name }
sitename () { return this.$store.state.instance.name },
navBarStyle () {
return { 'visibility': this.$route.name === 'chat' ? 'hidden' : 'visible' }
}
},
methods: {
toggleMobileSidebar () {
......
......@@ -3,6 +3,7 @@
<nav
id="nav"
class="nav-bar container"
:style="navBarStyle"
>
<div
class="mobile-inner-nav"
......
......@@ -40,7 +40,9 @@ const PostStatusForm = {
'maxHeight',
'poster',
'preserveFocus',
'autoFocus'
'autoFocus',
'fileLimit',
'submitOnEnter'
],
components: {
MediaUpload,
......@@ -91,7 +93,8 @@ const PostStatusForm = {
contentType
},
caret: 0,
pollFormVisible: false
pollFormVisible: false,
emojiInputShown: false
}
},
computed: {
......@@ -174,9 +177,14 @@ const PostStatusForm = {
...mapGetters(['mergedConfig'])
},
methods: {
postStatus (newStatus) {
postStatus (newStatus, opts = {}) {
if (this.posting) { return }
if (this.submitDisabled) { return }
if (this.emojiInputShown) { return }
if (opts.control && this.submitOnEnter) {
newStatus.status = `${newStatus.status}\n`
return
}
if (this.newStatus.status === '') {
if (this.newStatus.files.length === 0) {
......@@ -237,12 +245,19 @@ const PostStatusForm = {
})
},
addMediaFile (fileInfo) {
this.$emit('resize')
this.newStatus.files.push(fileInfo)
this.enableSubmit()
// TODO: use fixed dimensions instead so relying on timeout
setTimeout(() => {
this.$emit('resize')
}, 150)
},
removeMediaFile (fileInfo) {
this.$emit('resize')
let index = this.newStatus.files.indexOf(fileInfo)
this.newStatus.files.splice(index, 1)
this.$emit('resize')
},
uploadFailed (errString, templateArgs) {
templateArgs = templateArgs || {}
......@@ -397,6 +412,9 @@ const PostStatusForm = {
},
dismissScopeNotice () {
this.$store.dispatch('setOption', { name: 'hideScopeNotice', value: true })
},
handleEmojiInputShow (value) {
this.emojiInputShown = value
}
}
}
......
......@@ -86,6 +86,7 @@
@input="onEmojiInputInput"
@sticker-uploaded="addMediaFile"
@sticker-upload-failed="uploadFailed"
@shown="handleEmojiInputShow"
>
<textarea
ref="textarea"
......@@ -95,7 +96,8 @@
:disabled="posting"
class="form-post-body"
:class="{ 'scrollable-form': !!maxHeight }"
@keydown.meta.enter="postStatus(newStatus)"
@keydown.exact.stop.prevent.enter="submitOnEnter && postStatus(newStatus)"
@keydown.meta.enter="postStatus(newStatus, { control: true })"
@keyup.ctrl.enter="postStatus(newStatus)"
@drop="fileDrop"
@dragover.prevent="fileDrag"
......@@ -172,6 +174,7 @@
ref="mediaUpload"
class="media-upload-icon"
:drop-files="dropFiles"
:disabled="newStatus.files.length >= fileLimit"
@uploading="disableSubmit"
@uploaded="addMediaFile"
@upload-failed="uploadFailed"
......@@ -214,8 +217,9 @@
<button
v-else
:disabled="submitDisabled"
type="submit"
class="btn btn-default"
@touchstart.stop.prevent="postStatus(newStatus)"
@mousedown.stop.prevent="postStatus(newStatus)"
>
{{ $t('general.submit') }}
</button>
......
......@@ -84,7 +84,10 @@
"account_not_locked_warning_link": "gesperrt",
"attachments_sensitive": "Anhänge als heikel markieren",
"content_type": {
"text/plain": "Nur Text"
"text/plain": "Nur Text",
"text/bbcode": "BBCode",
"text/markdown": "Markdown",
"text/html": "HTML"
},
"content_warning": "Betreff (optional)",
"default": "Sitze gerade im Hofbräuhaus.",
......@@ -95,6 +98,13 @@
"private": "Nur Follower - Beitrag nur für Follower sichtbar",
"public": "Öffentlich - Beitrag an öffentliche Zeitleisten",
"unlisted": "Nicht gelistet - Nicht in öffentlichen Zeitleisten anzeigen"
},
"direct_warning_to_all": "Dieser Beitrag wird für alle erwähnten Benutzer sichtbar sein.",
"direct_warning_to_first_only": "Dieser Beitrag wird für alle Benutzer, die am Anfang der Nachricht erwähnt wurden, sichtbar sein.",
"scope_notice": {
"public": "Dieser Beitrag wird für alle sichtbar sein",
"private": "Dieser Beitrag wird nur für deine Follower sichtbar sein",
"unlisted": "Dieser Beitrag wird weder in der öffentlichen Zeitleiste noch im gesamten bekannten Netzwerk sichtbar sein"
}
},
"registration": {
......@@ -112,8 +122,11 @@
"email_required": "darf nicht leer sein",
"password_required": "darf nicht leer sein",
"password_confirmation_required": "darf nicht leer sein",
"password_confirmation_match": "sollte mit dem Passwort identisch sein."
}
"password_confirmation_match": "sollte mit dem Passwort identisch sein"
},
"bio_placeholder": "z.B.\nHallo, ich bin Lain.\nIch bin ein Anime Mödchen aus dem vorstädtischen Japan. Du kennst mich vielleicht vom Wired.",
"fullname_placeholder": "z.B. Lain Iwakura",
"username_placeholder": "z.B. lain"
},
"settings": {
"attachmentRadius": "Anhänge",
......@@ -125,7 +138,7 @@
"background": "Hintergrund",
"bio": "Bio",
"btnRadius": "Buttons",
"cBlue": "Blau (Antworten, Folgt dir)",
"cBlue": "Blau (Antworten, folgt dir)",
"cGreen": "Grün (Retweet)",
"cOrange": "Orange (Favorisieren)",
"cRed": "Rot (Abbrechen)",
......@@ -141,21 +154,21 @@
"data_import_export_tab": "Datenimport/-export",
"default_vis": "Standard-Sichtbarkeitsumfang",
"delete_account": "Account löschen",
"delete_account_description": "Lösche deinen Account und alle deine Nachrichten unwiderruflich.",
"delete_account_description": "Lösche deine Daten und deaktiviere deinen Account unwiderruflich.",
"delete_account_error": "Es ist ein Fehler beim Löschen deines Accounts aufgetreten. Tritt dies weiterhin auf, wende dich an den Administrator der Instanz.",
"delete_account_instructions": "Tippe dein Passwort unten in das Feld ein, um die Löschung deines Accounts zu bestätigen.",
"discoverable": "Erlaubnis für automatisches Suchen nach diesem Account",
"discoverable": "Erlaube, dass dieser Account in Suchergebnissen auftaucht",
"avatar_size_instruction": "Die empfohlene minimale Größe für Avatare ist 150x150 Pixel.",
"pad_emoji": "Emojis mit Leerzeichen umrahmen",
"export_theme": "Farbschema speichern",
"filtering": "Filtern",
"filtering_explanation": "Alle Beiträge die diese Wörter enthalten werden ausgeblendet. Ein Wort pro Zeile.",
"filtering_explanation": "Alle Beiträge, welche diese Wörter enthalten, werden ausgeblendet. Ein Wort pro Zeile.",
"follow_export": "Follower exportieren",
"follow_export_button": "Exportiere deine Follows in eine csv-Datei",
"follow_export_processing": "In Bearbeitung. Die Liste steht gleich zum herunterladen bereit.",
"follow_import": "Followers importieren",
"follow_import_error": "Fehler beim importieren der Follower",
"follows_imported": "Followers importiert! Die Bearbeitung kann eine Zeit lang dauern.",
"follow_import": "Follower importieren",
"follow_import_error": "Fehler beim Importieren der Follower",
"follows_imported": "Follower importiert! Die Bearbeitung kann einen Moment dauern.",
"foreground": "Vordergrund",
"general": "Allgemein",
"hide_attachments_in_convo": "Anhänge in Unterhaltungen ausblenden",
......@@ -168,7 +181,7 @@
"hide_post_stats": "Beitragsstatistiken verbergen (z.B. die Anzahl der Favoriten)",
"hide_user_stats": "Benutzerstatistiken verbergen (z.B. die Anzahl der Follower)",
"hide_filtered_statuses": "Gefilterte Beiträge verbergen",
"import_followers_from_a_csv_file": "Importiere Follower, denen du folgen möchtest, aus einer CSV-Datei",
"import_followers_from_a_csv_file": "Importiere Follower aus einer CSV-Datei",
"import_theme": "Farbschema laden",
"inputRadius": "Eingabefelder",
"checkboxRadius": "Auswahlfelder",
......@@ -182,7 +195,7 @@
"lock_account_description": "Sperre deinen Account, um neue Follower zu genehmigen oder abzulehnen",
"loop_video": "Videos wiederholen",
"loop_video_silent_only": "Nur Videos ohne Ton wiederholen (z.B. Mastodons \"gifs\")",
"mutes_tab": "Mutes",
"mutes_tab": "Stummschaltungen",
"play_videos_in_modal": "Videos in größerem Medienfenster abspielen",
"use_contain_fit": "Vorschaubilder nicht zuschneiden",
"name": "Name",
......@@ -355,7 +368,43 @@
"checkbox": "Ich habe die Allgemeinen Geschäftsbedingungen überflogen",
"link": "ein netter kleiner Link"
}
}
},
"app_name": "Anwendungsname",
"mfa": {
"otp": "OTP",
"recovery_codes_warning": "Schreibe dir die Codes auf oder speichere sie an einem sicheren Ort - ansonsten wirst du sie nicht wiederfinden. Wenn du den Zugriff zu deiner 2FA App und die Wiederherstellungs-Codes verlierst, wirst du aus deinem Account ausgeschlossen sein.",
"recovery_codes": "Wiederherstellungs-Codes.",
"warning_of_generate_new_codes": "Wenn du neue Wiederherstellungs-Codes generierst, werden die alten Codes nicht mehr funktionieren.",
"generate_new_recovery_codes": "Generiere neue Wiederherstellungs-Codes",
"title": "Zwei-Faktor Authentifizierung",
"waiting_a_recovery_codes": "Erhalte Wiederherstellungscodes...",
"authentication_methods": "Authentifizierungsmethoden",
"scan": {
"title": "Scan",
"secret_code": "Schlüssel",
"desc": "Wenn du deine 2FA App verwendest, scanne diesen QR Code oder gebe den Schlüssel ein:"
},
"verify": {
"desc": "Um 2FA zu aktivieren, gib den Code von deiner 2FA-App ein:"
}
},
"enter_current_password_to_confirm": "Gib dein aktuelles Passwort ein, um deine Identität zu bestätigen",
"security": "Sicherheit",
"allow_following_move": "Erlaube automatisches Folgen, sobald ein gefolgter Nutzer umzieht",
"blocks_imported": "Blocks importiert! Die Verarbeitung wird einen Moment brauchen.",
"block_import_error": "Fehler beim Importieren der Blocks",
"block_import": "Block Import",
"block_export_button": "Exportiere deine Blocks in eine csv Datei",
"block_export": "Block Export",
"emoji_reactions_on_timeline": "Zeige Emoji-Reaktionen auf der Zeitleiste",
"domain_mutes": "Domains",
"changed_email": "Email Adresse erfolgreich geändert!",
"change_email_error": "Es trat ein Problem auf beim Versuch, deine Email Adresse zu ändern.",
"change_email": "Ändere Email",
"notification_setting_non_followers": "Nutzer, die dir nicht folgen",
"notification_setting_followers": "Nutzer, die dir folgen",
"import_blocks_from_a_csv_file": "Importiere Blocks von einer CSV Datei",
"accent": "Akzent"
},
"timeline": {
"collapse": "Einklappen",
......@@ -378,7 +427,7 @@
"follow_again": "Anfrage erneut senden?",
"follow_unfollow": "Folgen beenden",
"followees": "Folgt",
"followers": "Followers",
"followers": "Folgende",
"following": "Folgst du!",
"follows_you": "Folgt dir!",
"its_you": "Das bist du!",
......@@ -386,7 +435,10 @@
"muted": "Stummgeschaltet",
"per_day": "pro Tag",
"remote_follow": "Folgen",
"statuses": "Beiträge"
"statuses": "Beiträge",
"admin_menu": {
"sandbox": "Erzwinge Beiträge nur für Follower sichtbar zu sein"
}
},
"user_profile": {
"timeline_title": "Beiträge"
......@@ -511,6 +563,22 @@
"search_emoji": "Nach einem Emoji suchen",
"custom": "Benutzerdefinierter Emoji",
"keep_open": "Auswahlfenster offen halten",
"add_emoji": "Emoji einfügen"
"add_emoji": "Emoji einfügen",
"load_all": "Lade alle {emojiAmount} Emoji",
"load_all_hint": "Erfolgreich erste {saneAmount} Emoji geladen, alle Emojis zu laden würde Leistungsprobleme hervorrufen.",
"unicode": "Unicode Emoji"
},
"interactions": {
"load_older": "Lade ältere Interaktionen",
"follows": "Neue Follows",
"favs_repeats": "Wiederholungen und Favoriten",
"moves": "Benutzer migriert zu"
},
"selectable_list": {
"select_all": "Wähle alle"
},
"remote_user_resolver": {
"searching_for": "Suche nach",
"error": "Nicht gefunden."
}
}
......@@ -20,7 +20,16 @@
"timeline": "Sequenza personale",
"twkn": "Sequenza globale",
"chat": "Chat della stanza",
"friend_requests": "Vogliono seguirti"
"friend_requests": "Vogliono seguirti",
"about": "Informazioni",
"administration": "Amministrazione",
"back": "Indietro",
"interactions": "Interazioni",
"dms": "Messaggi diretti",
"user_search": "Ricerca utenti",
"search": "Ricerca",
"who_to_follow": "Chi seguire",
"preferences": "Preferenze"
},
"notifications": {
"followed_you": "ti segue",
......@@ -29,7 +38,11 @@
"broken_favorite": "Stato sconosciuto, lo sto cercando...",
"favorited_you": "ha gradito il tuo messaggio",
"load_older": "Carica notifiche precedenti",
"repeated_you": "ha condiviso il tuo messaggio"
"repeated_you": "ha condiviso il tuo messaggio",
"follow_request": "vuole seguirti",
"no_more_notifications": "Fine delle notifiche",
"migrated_to": "è migrato verso",
"reacted_with": "ha reagito con"
},
"settings": {
"attachments": "Allegati",
......@@ -72,7 +85,7 @@
"data_import_export_tab": "Importa o esporta dati",
"default_vis": "Visibilità predefinita dei messaggi",
"delete_account": "Elimina profilo",
"delete_account_description": "Elimina definitivamente il tuo profilo e tutti i tuoi messaggi.",
"delete_account_description": "Elimina definitivamente i tuoi dati e disattiva il tuo profilo.",
"delete_account_error": "C'è stato un problema durante l'eliminazione del tuo profilo. Se il problema persiste contatta l'amministratore della tua stanza.",
"delete_account_instructions": "Digita la tua password nel campo sottostante per confermare l'eliminazione del tuo profilo.",
"export_theme": "Salva impostazioni",
......@@ -180,7 +193,16 @@
"placeholder": "es. Lupo Lucio",
"register": "Registrati",
"username": "Nome utente",
"description": "Accedi con OAuth"
"description": "Accedi con OAuth",
"hint": "Accedi per partecipare alla discussione",
"authentication_code": "Codice di autenticazione",
"enter_recovery_code": "Inserisci un codice di recupero",
"enter_two_factor_code": "Inserisci un codice two-factor",
"recovery_code": "Codice di recupero",
"heading": {
"totp": "Autenticazione two-factor",
"recovery": "Recupero two-factor"
}
},
"post_status": {
"account_not_locked_warning": "Il tuo profilo non è {0}. Chiunque può seguirti e vedere i tuoi messaggi riservati ai tuoi seguaci.",
......@@ -265,5 +287,37 @@
"submit": "Invia",
"success": "Importato.",
"error": "L'importazione non è andata a buon fine."
},
"media_modal": {
"previous": "Precedente",
"next": "Prossimo"
},
"polls": {
"add_poll": "Sondaggio",
"add_option": "Alternativa",
"option": "Opzione",
"votes": "voti",
"vote": "Vota",
"type": "Tipo di sondaggio",
"single_choice": "Scelta singola",
"multiple_choices": "Scelta multipla",
"expiry": "Scadenza",
"expires_in": "Scade fra {0}",
"expired": "Scaduto {0} fa",
"not_enough_options": "Aggiungi altre risposte"
},
"interactions": {
"favs_repeats": "Condivisi e preferiti"
},
"emoji": {
"load_all": "Carico tutti i {emojiAmount} emoji",
"load_all_hint": "Primi {saneAmount} emoji caricati, caricarli tutti potrebbe causare rallentamenti.",
"unicode": "Emoji Unicode",
"custom": "Emoji personale",
"add_emoji": "Inserisci Emoji",
"search_emoji": "Cerca un emoji",
"keep_open": "Tieni aperto il menù",
"emoji": "Emoji",
"stickers": "Adesivi"
}
}
This diff is collapsed.
This diff is collapsed.
......@@ -16,7 +16,9 @@
"verify": "Проверить",
"more": "Больше",
"generic_error": "Произошла ошибка",
"optional": "не обязательно"
"optional": "не обязательно",
"show_less": "Показать меньше",
"show_more": "Показать больше"
},
"login": {
"login": "Войти",
......
This diff is collapsed.
......@@ -66,6 +66,13 @@ const api = {
showImmediately: timelineData.visibleStatuses.length === 0,
timeline: 'friends'
})
} else if (message.event === 'pleroma:chat_update') {
dispatch('addChatMessages', {
chatId: message.chatUpdate.id,
messages: [message.chatUpdate.lastMessage]
})
dispatch('updateChatByAccountId', { accountId: message.chatUpdate.account.id })
// dispatch('updateUnreadChatCount', { userId, unreadChatCount })
}
}
)
......
......@@ -100,6 +100,10 @@ const chats = {
deleteChatMessage ({ rootState, commit, dispatch }, value) {
rootState.api.backendInteractor.deleteChatMessage(value)
commit('deleteChatMessage', { commit, ...value })
},
resetChats ({ commit, dispatch }) {
dispatch('clearCurrentChat')
commit('resetChats', { commit })
}
},
mutations: {
......@@ -154,8 +158,12 @@ const chats = {
state.chats.idStore = omitBy(state.chats.idStore, conversation => conversation.last_status.id === id)
},
resetChats (state, { _dispatch }) {
state.chats.data = []
state.chats.idStore = {}
state.chatList = emptyChatList()
state.chats.openedChats = {}
state.chats.openedChatMessageServices = {}
state.chats.fetcher = undefined
state.chats.chatFocused = false
state.chats.currentChatId = null
},
setChatsLoading (state, { value }) {
state.chats.loading = value
......
......@@ -12,7 +12,8 @@ const defaultState = {
window.CSS.supports('-webkit-filter', 'drop-shadow(0 0)')
)
},
mobileLayout: false
mobileLayout: false,
layoutHeight: 0
}
const interfaceMod = {
......@@ -35,6 +36,9 @@ const interfaceMod = {
},
setMobileLayout (state, value) {
state.mobileLayout = value
},
setLayoutHeight (state, value) {
state.layoutHeight = value
}
},
actions: {
......@@ -49,6 +53,9 @@ const interfaceMod = {
},
setMobileLayout ({ commit }, value) {
commit('setMobileLayout', value)
},
setLayoutHeight ({ commit }, value) {
commit('setLayoutHeight', value)
}
}
}
......
......@@ -495,6 +495,7 @@ const users = {
store.dispatch('stopFetchingFollowRequests')
store.commit('clearNotifications')
store.commit('resetStatuses')
store.dispatch('resetChats')
})
},
loginUser (store, accessToken) {
......
......@@ -543,9 +543,11 @@ const fetchTimeline = ({
if (timeline === 'public' || timeline === 'publicAndExternal') {
params.push(['only_media', false])
}
if (timeline !== 'favorites') {
params.push(['with_muted', withMuted])
}
params.push(['limit', 20])
params.push(['with_muted', withMuted])
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
url += `?${queryString}`
......@@ -1049,6 +1051,10 @@ const MASTODON_STREAMING_EVENTS = new Set([
'filters_changed'
])
const PLEROMA_STREAMING_EVENTS = new Set([
'pleroma:chat_update'
])
// A thin wrapper around WebSocket API that allows adding a pre-processor to it
// Uses EventTarget and a CustomEvent to proxy events
export const ProcessedWS = ({
......@@ -1105,7 +1111,7 @@ export const handleMastoWS = (wsEvent) => {
if (!data) return
const parsedEvent = JSON.parse(data)
const { event, payload } = parsedEvent
if (MASTODON_STREAMING_EVENTS.has(event)) {
if (MASTODON_STREAMING_EVENTS.has(event) || PLEROMA_STREAMING_EVENTS.has(event)) {
// MastoBE and PleromaBE both send payload for delete as a PLAIN string
if (event === 'delete') {
return { event, id: payload }
......@@ -1115,6 +1121,8 @@ export const handleMastoWS = (wsEvent) => {
return { event, status: parseStatus(data) }
} else if (event === 'notification') {
return { event, notification: parseNotification(data) }
} else if (event === 'pleroma:chat_update') {
return { event, chatUpdate: parseChat(data) }
}
} else {
console.warn('Unknown event', wsEvent)
......
......@@ -3,3 +3,8 @@ export const windowWidth = () =>
window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth
export const windowHeight = () =>
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight
......@@ -7951,6 +7951,11 @@ wavesurfer.js@^3.3.3:
resolved "https://registry.yarnpkg.com/wavesurfer.js/-/wavesurfer.js-3.3.3.tgz#9b16a62335c6bd13a3d55deb895a336d027ccb51"
integrity sha512-meko20S9in+V5xBLSVV/9uYVBSbx5AsJNkAslZ+a5yYIeFGYwcCo4Yd1sUpSGaiNnyflzrJwC7x7TdJFYrdT8w==
wavesurfer@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/wavesurfer/-/wavesurfer-1.3.4.tgz#17908abd20da11a8db460c5a176679621d519bfa"
integrity sha1-F5CKvSDaEajbRgxaF2Z5Yh1Rm/o=
webpack-dev-middleware@^3.2.0, webpack-dev-middleware@^3.6.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz#ef751d25f4e9a5c8a35da600c5fda3582b5c6cff"
......