aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.js7
-rw-r--r--src/App.vue1
-rw-r--r--src/components/instance_specific_panel/instance_specific_panel.js9
-rw-r--r--src/components/instance_specific_panel/instance_specific_panel.vue15
-rw-r--r--src/components/post_status_form/post_status_form.js15
-rw-r--r--src/components/post_status_form/post_status_form.vue11
-rw-r--r--src/components/status/status.vue2
-rw-r--r--src/components/style_switcher/style_switcher.vue79
-rw-r--r--src/components/timeline/timeline.vue4
-rw-r--r--src/components/user_settings/user_settings.vue2
-rw-r--r--src/i18n/messages.js126
-rw-r--r--src/main.js22
12 files changed, 254 insertions, 39 deletions
diff --git a/src/App.js b/src/App.js
index 8e7acb42..e9248967 100644
--- a/src/App.js
+++ b/src/App.js
@@ -2,6 +2,7 @@ import UserPanel from './components/user_panel/user_panel.vue'
import NavPanel from './components/nav_panel/nav_panel.vue'
import Notifications from './components/notifications/notifications.vue'
import UserFinder from './components/user_finder/user_finder.vue'
+import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue'
import ChatPanel from './components/chat_panel/chat_panel.vue'
export default {
@@ -11,7 +12,8 @@ export default {
NavPanel,
Notifications,
UserFinder,
- ChatPanel
+ ChatPanel,
+ InstanceSpecificPanel
},
data: () => ({
mobileActivePanel: 'timeline'
@@ -24,7 +26,8 @@ export default {
logoStyle () { return { 'background-image': `url(${this.$store.state.config.logo})` } },
style () { return { 'background-image': `url(${this.background})` } },
sitename () { return this.$store.state.config.name },
- chat () { return this.$store.state.chat.channel.state === 'joined' }
+ chat () { return this.$store.state.chat.channel.state === 'joined' },
+ showInstanceSpecificPanel () { return this.$store.state.config.showInstanceSpecificPanel }
},
methods: {
activatePanel (panelName) {
diff --git a/src/App.vue b/src/App.vue
index ec403519..2a910bc0 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -23,6 +23,7 @@
<div class="sidebar">
<user-panel></user-panel>
<nav-panel></nav-panel>
+ <instance-specific-panel v-if="showInstanceSpecificPanel"></instance-specific-panel>
<chat-panel v-if="currentUser && chat"></chat-panel>
<notifications v-if="currentUser"></notifications>
</div>
diff --git a/src/components/instance_specific_panel/instance_specific_panel.js b/src/components/instance_specific_panel/instance_specific_panel.js
new file mode 100644
index 00000000..abd408c8
--- /dev/null
+++ b/src/components/instance_specific_panel/instance_specific_panel.js
@@ -0,0 +1,9 @@
+const InstanceSpecificPanel = {
+ computed: {
+ instanceSpecificPanelContent () {
+ return this.$store.state.config.instanceSpecificPanelContent
+ }
+ }
+}
+
+export default InstanceSpecificPanel
diff --git a/src/components/instance_specific_panel/instance_specific_panel.vue b/src/components/instance_specific_panel/instance_specific_panel.vue
new file mode 100644
index 00000000..b3ea019d
--- /dev/null
+++ b/src/components/instance_specific_panel/instance_specific_panel.vue
@@ -0,0 +1,15 @@
+<template>
+ <div class="instance-specific-panel">
+ <div class="panel panel-default base01-background">
+ <div class="panel-body">
+ <div v-html="instanceSpecificPanelContent">
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script src="./instance_specific_panel.js" ></script>
+
+<style lang="scss">
+</style>
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index d4290c85..999aa732 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -98,6 +98,21 @@ const PostStatusForm = {
},
customEmoji () {
return this.$store.state.config.customEmoji || []
+ },
+ statusLength () {
+ return this.newStatus.status.length
+ },
+ statusLengthLimit () {
+ return this.$store.state.config.textlimit
+ },
+ hasStatusLengthLimit () {
+ return this.statusLengthLimit > 0
+ },
+ charactersLeft () {
+ return this.statusLengthLimit - this.statusLength
+ },
+ isOverLengthLimit () {
+ return this.hasStatusLengthLimit && (this.statusLength > this.statusLengthLimit)
}
},
methods: {
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 4a6a574a..4871bcae 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -22,7 +22,12 @@
</div>
<div class='form-bottom'>
<media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="enableSubmit" :drop-files="dropFiles"></media-upload>
+
+ <p v-if="isOverLengthLimit" class="error">{{ charactersLeft }}</p>
+ <p v-else-if="hasStatusLengthLimit" class="base04">{{ charactersLeft }}</p>
+
<button v-if="posting" disabled class="btn btn-default base05 base02-background">{{$t('post_status.posting')}}</button>
+ <button v-else-if="isOverLengthLimit" disabled class="btn btn-default base05 base02-background">{{$t('general.submit')}}</button>
<button v-else :disabled="submitDisabled" type="submit" class="btn btn-default base05 base02-background">{{$t('general.submit')}}</button>
</div>
<div class='error' v-if="error">
@@ -71,6 +76,12 @@
button {
width: 10em;
}
+
+ p {
+ margin: 0.35em;
+ padding: 0.35em;
+ display: flex;
+ }
}
.error {
border-radius: 5px;
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index f6afaa25..28272b0b 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -100,7 +100,7 @@
<div @click.prevent="linkClicked" class="status-content" v-html="status.statusnet_html"></div>
<div v-if='status.attachments' class='attachments'>
- <attachment v-if="!hideAttachments" :status-id="status.id" :nsfw="status.nsfw" :attachment="attachment" v-for="attachment in status.attachments">
+ <attachment v-if="!hideAttachments" :status-id="status.id" :nsfw="status.nsfw" :attachment="attachment" v-for="attachment in status.attachments" :key="attachment.id">
</attachment>
</div>
</div>
diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue
index f92f7299..31bf546d 100644
--- a/src/components/style_switcher/style_switcher.vue
+++ b/src/components/style_switcher/style_switcher.vue
@@ -7,20 +7,24 @@
<p>{{$t('settings.theme_help')}}</p>
<div class="color-container">
<div class="color-item">
- <label for="bgcolor" class="base04">{{$t('settings.background')}}</label>
- <input id="bgcolor" class="theme-color-in" type="text" v-model="bgColorLocal">
+ <label for="bgcolor" class="base04 theme-color-lb">{{$t('settings.background')}}</label>
+ <input id="bgcolor" class="theme-color-cl" type="color" v-model="bgColorLocal">
+ <input id="bgcolor-t" class="theme-color-in" type="text" v-model="bgColorLocal">
</div>
<div class="color-item">
- <label for="fgcolor" class="base04">{{$t('settings.foreground')}}</label>
- <input id="fgcolor" class="theme-color-in" type="text" v-model="fgColorLocal">
+ <label for="fgcolor" class="base04 theme-color-lb">{{$t('settings.foreground')}}</label>
+ <input id="fgcolor" class="theme-color-cl" type="color" v-model="fgColorLocal">
+ <input id="fgcolor-t" class="theme-color-in" type="text" v-model="fgColorLocal">
</div>
<div class="color-item">
- <label for="textcolor" class="base04">{{$t('settings.text')}}</label>
- <input id="textcolor" class="theme-color-in" type="text" v-model="textColorLocal">
+ <label for="textcolor" class="base04 theme-color-lb">{{$t('settings.text')}}</label>
+ <input id="textcolor" class="theme-color-cl" type="color" v-model="textColorLocal">
+ <input id="textcolor-t" class="theme-color-in" type="text" v-model="textColorLocal">
</div>
<div class="color-item">
- <label for="linkcolor" class="base04">{{$t('settings.links')}}</label>
- <input id="linkcolor" class="theme-color-in" type="text" v-model="linkColorLocal">
+ <label for="linkcolor" class="base04 theme-color-lb">{{$t('settings.links')}}</label>
+ <input id="linkcolor" class="theme-color-cl" type="color" v-model="linkColorLocal">
+ <input id="linkcolor-t" class="theme-color-in" type="text" v-model="linkColorLocal">
</div>
</div>
<div>
@@ -43,27 +47,50 @@
<script src="./style_switcher.js"></script>
<style lang="scss">
- .style-switcher {
- margin-right: 1em;
- }
+.style-switcher {
+ margin-right: 1em;
+}
- .color-container {
- display: flex;
- flex-wrap: wrap;
- }
+.color-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+}
- .color-item {
- max-width: 9em;
- display:flex;
- flex-wrap:wrap;
- }
+.color-item {
+ min-width: 20em;
+ display:flex;
+ flex: 1 1 0;
+ align-items: baseline;
+ margin: 5px 6px 5px 0;
+}
+.theme-color-cl,
+.theme-color-in {
+ margin-left: 4px;
+ border-radius: 2px;
+ border: 0;
+}
+
+.theme-color-in {
+ padding: 5px;
+ min-width: 4em;
+ max-width: 7em;
+ flex: 1;
+}
+.theme-color-lb {
+ flex: 2;
+ min-width: 7em;
+ max-width: 10em;
+}
- .theme-color-in {
- max-width: 8em;
- border-radius: 2px;
- border: 0;
- padding: 5px;
- margin: 5px 0 5px 0;
+.theme-color-cl {
+ padding: 1px;
+ max-width: 8em;
+ align-self: stretch;
+ height: 100%;
+ flex: 0;
+ min-width: 2em;
+ cursor: pointer;
}
.theme-preview-content {
diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index 9d2e1ea1..d6ecfd2f 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -32,7 +32,7 @@
</div>
<div class="panel-body base01-background">
<div class="timeline">
- <user-card v-for="follower in followers" :user="follower" :showFollows="false"></user-card>
+ <user-card v-for="follower in followers" :key="follower.id" :user="follower" :showFollows="false"></user-card>
</div>
</div>
</div>
@@ -44,7 +44,7 @@
</div>
<div class="panel-body base01-background">
<div class="timeline">
- <user-card v-for="friend in friends" :user="friend" :showFollows="true"></user-card>
+ <user-card v-for="friend in friends" :key="friend.id" :user="friend" :showFollows="true"></user-card>
</div>
</div>
</div>
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index da78cdc2..1ef52bbf 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -7,7 +7,7 @@
<div class="setting-item">
<h3>{{$t('settings.name_bio')}}</h3>
<p>{{$t('settings.name')}}</p>
- <input class='name-changer base03-border' id='username' v-model="newname" :value="user.screen_name"></input>
+ <input class='name-changer base03-border' id='username' v-model="newname"></input>
<p>{{$t('settings.bio')}}</p>
<textarea class="bio base03-border" v-model="newbio"></textarea>
<button :disabled='newname.length <= 0' class="btn btn-default base05 base02-background" @click="updateProfile">{{$t('general.submit')}}</button>
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index f3f1e2d4..c4a62128 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -840,7 +840,11 @@ const pl = {
}
const es = {
+ chat: {
+ title: 'Chat'
+ },
nav: {
+ chat: 'Chat Local',
timeline: 'Línea Temporal',
mentions: 'Menciones',
public_tl: 'Línea Temporal Pública',
@@ -857,7 +861,8 @@ const es = {
muted: 'Silenciado',
followers: 'Seguidores',
followees: 'Siguiendo',
- per_day: 'por día'
+ per_day: 'por día',
+ remote_follow: 'Seguir'
},
timeline: {
show_new: 'Mostrar lo nuevo',
@@ -881,6 +886,12 @@ const es = {
set_new_profile_background: 'Cambiar fondo del perfil',
settings: 'Ajustes',
theme: 'Tema',
+ presets: 'Por defecto',
+ theme_help: 'Use códigos de color hexadecimales (#aabbcc) para personalizar su tema de colores.',
+ background: 'Segundo plano',
+ foreground: 'Primer plano',
+ text: 'Texto',
+ links: 'Links',
filtering: 'Filtros',
filtering_explanation: 'Todos los estados que contengan estas palabras serán silenciados, una por línea',
attachments: 'Adjuntos',
@@ -888,7 +899,12 @@ const es = {
hide_attachments_in_convo: 'Ocultar adjuntos en las conversaciones',
nsfw_clickthrough: 'Activar el clic para ocultar los adjuntos NSFW',
autoload: 'Activar carga automática al llegar al final de la página',
- reply_link_preview: 'Activar la previsualización del enlace de responder al pasar el ratón por encima'
+ streaming: 'Habilite la transmisión automática de nuevas publicaciones cuando se desplaza hacia la parte superior',
+ reply_link_preview: 'Activar la previsualización del enlace de responder al pasar el ratón por encima',
+ follow_import: 'Importar personas que tú sigues',
+ import_followers_from_a_csv_file: 'Importar personas que tú sigues apartir de un archivo csv',
+ follows_imported: '¡Importado! Procesarlos llevará tiempo.',
+ follow_import_error: 'Error al importal el archivo'
},
notifications: {
notifications: 'Notificaciones',
@@ -918,7 +934,8 @@ const es = {
error_fetching_user: 'Error al buscar usuario'
},
general: {
- submit: 'Enviar'
+ submit: 'Enviar',
+ apply: 'Aplicar'
}
}
@@ -1021,6 +1038,106 @@ const pt = {
}
}
+const ru = {
+ chat: {
+ title: 'Чат'
+ },
+ nav: {
+ chat: 'Локальный чат',
+ timeline: 'Лента',
+ mentions: 'Упоминания',
+ public_tl: 'Публичная лента',
+ twkn: 'Федеративная лента'
+ },
+ user_card: {
+ follows_you: 'Читает вас',
+ following: 'Читаю',
+ follow: 'Читать',
+ blocked: 'Заблокирован',
+ block: 'Заблокировать',
+ statuses: 'Статусы',
+ mute: 'Игнорировать',
+ muted: 'Игнорирую',
+ followers: 'Читатели',
+ followees: 'Читаемые',
+ per_day: 'в день',
+ remote_follow: 'Читать удалённо'
+ },
+ timeline: {
+ show_new: 'Показать новые',
+ error_fetching: 'Ошибка при обновлении',
+ up_to_date: 'Обновлено',
+ load_older: 'Загрузить старые статусы',
+ conversation: 'Разговор'
+ },
+ settings: {
+ user_settings: 'Настройки пользователя',
+ name_bio: 'Имя и описание',
+ name: 'Имя',
+ bio: 'Описание',
+ avatar: 'Аватар',
+ current_avatar: 'Текущий аватар',
+ set_new_avatar: 'Загрузить новый аватар',
+ profile_banner: 'Баннер профиля',
+ current_profile_banner: 'Текущий баннер профиля',
+ set_new_profile_banner: 'Загрузить новый баннер профиля',
+ profile_background: 'Фон профиля',
+ set_new_profile_background: 'Загрузить новый фон профиля',
+ settings: 'Настройки',
+ theme: 'Тема',
+ presets: 'Пресеты',
+ theme_help: 'Используйте шестнадцатеричные коды цветов (#aabbcc) для настройки темы.',
+ background: 'Фон',
+ foreground: 'Передний план',
+ text: 'Текст',
+ links: 'Ссылки',
+ filtering: 'Фильтрация',
+ filtering_explanation: 'Все статусы, содержащие данные слова, будут игнорироваться, по одному в строке',
+ attachments: 'Вложения',
+ hide_attachments_in_tl: 'Прятать вложения в ленте',
+ hide_attachments_in_convo: 'Прятать вложения в разговорах',
+ nsfw_clickthrough: 'Включить скрытие NSFW вложений',
+ autoload: 'Включить автоматическую загрузку при прокрутке вниз',
+ streaming: 'Включить автоматическую загрузку новых сообщений при прокрутке вверх',
+ reply_link_preview: 'Включить предварительный просмотр ответа при наведении мыши',
+ follow_import: 'Импортировать читаемых',
+ import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv',
+ follows_imported: 'Список читаемых импортирован. Обработка займёт некоторое время..',
+ follow_import_error: 'Ошибка при импортировании читаемых.'
+ },
+ notifications: {
+ notifications: 'Уведомления',
+ read: 'Прочесть',
+ followed_you: 'начал читать вас'
+ },
+ login: {
+ login: 'Войти',
+ username: 'Имя пользователя',
+ password: 'Пароль',
+ register: 'Зарегистрироваться',
+ logout: 'Выйти'
+ },
+ registration: {
+ registration: 'Регистрация',
+ fullname: 'Отображаемое имя',
+ email: 'Email',
+ bio: 'Описание',
+ password_confirm: 'Подтверждение пароля'
+ },
+ post_status: {
+ posting: 'Отправляется',
+ default: 'Что нового?'
+ },
+ finder: {
+ find_user: 'Найти пользователя',
+ error_fetching_user: 'Пользователь не найден'
+ },
+ general: {
+ submit: 'Отправить',
+ apply: 'Применить'
+ }
+}
+
const messages = {
de,
fi,
@@ -1033,7 +1150,8 @@ const messages = {
it,
pl,
es,
- pt
+ pt,
+ ru
}
export default messages
diff --git a/src/main.js b/src/main.js
index a14ca7c8..6f8c00f0 100644
--- a/src/main.js
+++ b/src/main.js
@@ -75,15 +75,24 @@ const i18n = new VueI18n({
messages
})
-window.fetch('/static/config.json')
+window.fetch('/api/statusnet/config.json')
.then((res) => res.json())
.then((data) => {
- const {name, theme, background, logo, registrationOpen} = data
+ const {name, closed: registrationClosed, textlimit} = data.site
+
store.dispatch('setOption', { name: 'name', value: name })
+ store.dispatch('setOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
+ store.dispatch('setOption', { name: 'textlimit', value: parseInt(textlimit) })
+ })
+
+window.fetch('/static/config.json')
+ .then((res) => res.json())
+ .then((data) => {
+ const {theme, background, logo, showInstanceSpecificPanel} = data
store.dispatch('setOption', { name: 'theme', value: theme })
store.dispatch('setOption', { name: 'background', value: background })
store.dispatch('setOption', { name: 'logo', value: logo })
- store.dispatch('setOption', { name: 'registrationOpen', value: registrationOpen })
+ store.dispatch('setOption', { name: 'showInstanceSpecificPanel', value: showInstanceSpecificPanel })
if (data['chatDisabled']) {
store.dispatch('disableChat')
}
@@ -155,3 +164,10 @@ window.fetch('/static/emoji.json')
})
store.dispatch('setOption', { name: 'emoji', value: emoji })
})
+
+window.fetch('/instance/panel.html')
+ .then((res) => res.text())
+ .then((html) => {
+ store.dispatch('setOption', { name: 'instanceSpecificPanelContent', value: html })
+ })
+