diff --git a/src/App.js b/src/App.js
index a052e058..39c97a80 100644
--- a/src/App.js
+++ b/src/App.js
@@ -29,7 +29,7 @@ export default {
style () { return { 'background-image': `url(${this.background})` } },
sitename () { return this.$store.state.config.name },
chat () { return this.$store.state.chat.channel.state === 'joined' },
- showWhoToFollowPanel () { return this.$store.state.config.showWhoToFollowPanel },
+ suggestionsEnabled () { return this.$store.state.config.suggestionsEnabled },
showInstanceSpecificPanel () { return this.$store.state.config.showInstanceSpecificPanel }
},
methods: {
diff --git a/src/App.scss b/src/App.scss
index ae6561a9..3b8b3224 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -63,8 +63,6 @@ button{
box-shadow: 0px 0px 2px black;
font-size: 14px;
font-family: sans-serif;
- min-width: 10em;
- min-height: 2em;
&:hover {
box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3);
diff --git a/src/App.vue b/src/App.vue
index 923d411b..71e90289 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -24,7 +24,7 @@
-
+
diff --git a/src/components/login_form/login_form.vue b/src/components/login_form/login_form.vue
index d2bdffcb..b7fed48a 100644
--- a/src/components/login_form/login_form.vue
+++ b/src/components/login_form/login_form.vue
@@ -34,6 +34,11 @@
@import '../../_variables.scss';
.login-form {
+ .btn {
+ min-height: 28px;
+ width: 10em;
+ }
+
.error {
text-align: center;
}
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 1e1c6f1d..2b84758b 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -107,6 +107,10 @@
padding: 0.5em;
height: 32px;
+ button {
+ width: 10em;
+ }
+
p {
margin: 0.35em;
padding: 0.35em;
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index c85ef59f..d5ca33cc 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -8,6 +8,7 @@ const settings = {
hideAttachmentsLocal: this.$store.state.config.hideAttachments,
hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
hideNsfwLocal: this.$store.state.config.hideNsfw,
+ replyVisibilityLocal: this.$store.state.config.replyVisibility,
loopVideoLocal: this.$store.state.config.loopVideo,
loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly,
muteWordsString: this.$store.state.config.muteWords.join('\n'),
@@ -44,6 +45,9 @@ const settings = {
hideNsfwLocal (value) {
this.$store.dispatch('setOption', { name: 'hideNsfw', value })
},
+ replyVisibilityLocal (value) {
+ this.$store.dispatch('setOption', { name: 'replyVisibility', value })
+ },
loopVideoLocal (value) {
this.$store.dispatch('setOption', { name: 'loopVideo', value })
},
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 170f5773..9612876e 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -38,6 +38,16 @@
+
+
+
@@ -117,6 +127,8 @@
.btn {
margin-top: 1em;
+ min-height: 28px;
+ width: 10em;
}
}
.setting-list {
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 9670f69d..11b8feba 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -83,7 +83,6 @@ const Status = {
return hits
},
muted () { return !this.unmuted && (this.status.user.muted || this.muteWordHits.length > 0) },
- isReply () { return !!this.status.in_reply_to_status_id },
isFocused () {
// retweet or root of an expanded conversation
if (this.focused) {
@@ -105,6 +104,48 @@ const Status = {
const lengthScore = this.status.statusnet_html.split(/
20
},
+ isReply () {
+ if (this.status.in_reply_to_status_id) {
+ return true
+ }
+ // For private replies where we can't see the OP, in_reply_to_status_id will be null.
+ // So instead, check that the post starts with a @mention.
+ if (this.status.visibility === 'private') {
+ var textBody = this.status.text
+ if (this.status.summary !== null) {
+ textBody = textBody.substring(this.status.summary.length, textBody.length)
+ }
+ return textBody.startsWith('@')
+ }
+ return false
+ },
+ hideReply () {
+ if (this.$store.state.config.replyVisibility === 'all') {
+ return false
+ }
+ if (this.inlineExpanded || this.expanded || this.inConversation || !this.isReply) {
+ return false
+ }
+ if (this.status.user.id === this.$store.state.users.currentUser.id) {
+ return false
+ }
+ if (this.status.activity_type === 'repeat') {
+ return false
+ }
+ var checkFollowing = this.$store.state.config.replyVisibility === 'following'
+ for (var i = 0; i < this.status.attentions.length; ++i) {
+ if (this.status.user.id === this.status.attentions[i].id) {
+ continue
+ }
+ if (checkFollowing && this.status.attentions[i].following) {
+ return false
+ }
+ if (this.status.attentions[i].id === this.$store.state.users.currentUser.id) {
+ return false
+ }
+ }
+ return this.status.attentions.length > 0
+ },
hideSubjectStatus () {
if (this.tallStatus && !this.$store.state.config.collapseMessageWithSubject) {
return false
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index e7d5ed7a..2bc44ee7 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -1,5 +1,5 @@
-
+
{{status.user.screen_name}}
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index 71222d15..59358040 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -105,8 +105,8 @@
{{user.followers_count}}
-
-
{{ user.description }}
+
+
{{ user.description }}
@@ -130,7 +130,11 @@
.profile-panel-body {
word-wrap: break-word;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--bg 80%);
- background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%)
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%);
+
+ .profile-bio {
+ text-align: center;
+ }
}
.user-info {
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.js b/src/components/who_to_follow_panel/who_to_follow_panel.js
index 51b9f469..6766e561 100644
--- a/src/components/who_to_follow_panel/who_to_follow_panel.js
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.js
@@ -1,5 +1,7 @@
-function showWhoToFollow (panel, reply, aHost, aUser) {
- var users = reply.ids
+import apiService from '../../services/api/api.service.js'
+
+function showWhoToFollow (panel, reply) {
+ var users = reply
var cn
var index = 0
var random = Math.floor(Math.random() * 10)
@@ -7,12 +9,12 @@ function showWhoToFollow (panel, reply, aHost, aUser) {
var user
user = users[cn]
var img
- if (user.icon) {
- img = user.icon
+ if (user.avatar) {
+ img = user.avatar
} else {
img = '/images/avi.png'
}
- var name = user.to_id
+ var name = user.acct
if (index === 0) {
panel.img1 = img
panel.name1 = name
@@ -52,27 +54,15 @@ function showWhoToFollow (panel, reply, aHost, aUser) {
}
function getWhoToFollow (panel) {
- var user = panel.$store.state.users.currentUser.screen_name
- if (user) {
+ var credentials = panel.$store.state.users.currentUser.credentials
+ if (credentials) {
panel.name1 = 'Loading...'
panel.name2 = 'Loading...'
panel.name3 = 'Loading...'
- var host = window.location.hostname
- var whoToFollowProvider = panel.$store.state.config.whoToFollowProvider
- var url
- url = whoToFollowProvider.replace(/{{host}}/g, encodeURIComponent(host))
- url = url.replace(/{{user}}/g, encodeURIComponent(user))
- window.fetch(url, {mode: 'cors'}).then(function (response) {
- if (response.ok) {
- return response.json()
- } else {
- panel.name1 = ''
- panel.name2 = ''
- panel.name3 = ''
- }
- }).then(function (reply) {
- showWhoToFollow(panel, reply, host, user)
- })
+ apiService.suggestions({credentials: credentials})
+ .then((reply) => {
+ showWhoToFollow(panel, reply)
+ })
}
}
@@ -95,26 +85,26 @@ const WhoToFollowPanel = {
moreUrl: function () {
var host = window.location.hostname
var user = this.user
- var whoToFollowLink = this.$store.state.config.whoToFollowLink
+ var suggestionsWeb = this.$store.state.config.suggestionsWeb
var url
- url = whoToFollowLink.replace(/{{host}}/g, encodeURIComponent(host))
+ url = suggestionsWeb.replace(/{{host}}/g, encodeURIComponent(host))
url = url.replace(/{{user}}/g, encodeURIComponent(user))
return url
},
- showWhoToFollowPanel () {
- return this.$store.state.config.showWhoToFollowPanel
+ suggestionsEnabled () {
+ return this.$store.state.config.suggestionsEnabled
}
},
watch: {
user: function (user, oldUser) {
- if (this.showWhoToFollowPanel) {
+ if (this.suggestionsEnabled) {
getWhoToFollow(this)
}
}
},
mounted:
function () {
- if (this.showWhoToFollowPanel) {
+ if (this.suggestionsEnabled) {
getWhoToFollow(this)
}
}
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.vue b/src/components/who_to_follow_panel/who_to_follow_panel.vue
index 5af6d0d5..8b3abe70 100644
--- a/src/components/who_to_follow_panel/who_to_follow_panel.vue
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.vue
@@ -3,7 +3,7 @@
- Who to follow
+ {{$t('who_to_follow.who_to_follow')}}
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index 00c56254..a0b7f562 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -325,6 +325,9 @@ const en = {
loop_video: 'Loop videos',
loop_video_silent_only: 'Loop only videos without sound (i.e. Mastodon\'s "gifs")',
reply_link_preview: 'Enable reply-link preview on mouse hover',
+ reply_visibility_all: 'Show all replies',
+ reply_visibility_following: 'Only show replies directed at me or users I\'m following',
+ reply_visibility_self: 'Only show replies directed at me',
follow_import: 'Follow import',
import_followers_from_a_csv_file: 'Import follows from a csv file',
follows_imported: 'Follows imported! Processing them will take a while.',
@@ -398,6 +401,10 @@ const en = {
},
user_profile: {
timeline_title: 'User Timeline'
+ },
+ who_to_follow: {
+ who_to_follow: 'Who to follow',
+ more: 'More'
}
}
@@ -781,115 +788,147 @@ const ja = {
chat: 'ローカルチャット',
timeline: 'タイムライン',
mentions: 'メンション',
- public_tl: '公開タイムライン',
- twkn: '接続しているすべてのネットワーク'
+ public_tl: 'パブリックタイムライン',
+ twkn: 'つながっているすべてのネットワーク',
+ friend_requests: 'Follow Requests'
},
user_card: {
follows_you: 'フォローされました!',
- following: 'フォロー中!',
+ following: 'フォローしています!',
follow: 'フォロー',
- blocked: 'ブロック済み!',
+ blocked: 'ブロックしています!',
block: 'ブロック',
- statuses: '投稿',
+ statuses: 'ステータス',
mute: 'ミュート',
- muted: 'ミュート済み',
+ muted: 'ミュートしています!',
followers: 'フォロワー',
followees: 'フォロー',
per_day: '/日',
- remote_follow: 'リモートフォロー'
+ remote_follow: 'リモートフォロー',
+ approve: 'Approve',
+ deny: 'Deny'
},
timeline: {
- show_new: '更新',
- error_fetching: '更新の取得中にエラーが発生しました。',
- up_to_date: '最新',
- load_older: '古い投稿を読み込む',
- conversation: '会話',
- collapse: '折り畳む',
+ show_new: 'よみこみ',
+ error_fetching: 'よみこみがエラーになりました。',
+ up_to_date: 'さいしん',
+ load_older: 'ふるいステータス',
+ conversation: 'スレッド',
+ collapse: 'たたむ',
repeated: 'リピート'
},
settings: {
- user_settings: 'ユーザー設定',
- name_bio: '名前とプロフィール',
- name: '名前',
+ user_settings: 'ユーザーせってい',
+ name_bio: 'なまえとプロフィール',
+ name: 'なまえ',
bio: 'プロフィール',
avatar: 'アバター',
- current_avatar: 'あなたの現在のアバター',
- set_new_avatar: '新しいアバターを設定する',
+ current_avatar: 'いまのアバター',
+ set_new_avatar: 'あたらしいアバターをせっていする',
profile_banner: 'プロフィールバナー',
- current_profile_banner: '現在のプロフィールバナー',
- set_new_profile_banner: '新しいプロフィールバナーを設定する',
- profile_background: 'プロフィールの背景',
- set_new_profile_background: '新しいプロフィールの背景を設定する',
- settings: '設定',
+ current_profile_banner: 'いまのプロフィールバナー',
+ set_new_profile_banner: 'あたらしいプロフィールバナーを設定する',
+ profile_background: 'プロフィールのバックグラウンド',
+ set_new_profile_background: 'あたらしいプロフィールのバックグラウンドをせっていする',
+ settings: 'せってい',
theme: 'テーマ',
presets: 'プリセット',
- theme_help: '16進数カラーコード (#aabbcc) を使用してカラーテーマをカスタマイズ出来ます。',
- radii_help: 'インターフェースの縁の丸さを設定する。',
- background: '背景',
- foreground: '前景',
- text: '文字',
+ theme_help: 'カラーテーマをカスタマイズできます。',
+ radii_help: 'インターフェースのまるさをせっていする。',
+ background: 'バックグラウンド',
+ foreground: 'フォアグラウンド',
+ text: 'もじ',
links: 'リンク',
- cBlue: '青 (返信, フォロー)',
- cRed: '赤 (キャンセル)',
- cOrange: 'オレンジ (お気に入り)',
- cGreen: '緑 (リツイート)',
+ cBlue: 'あお (リプライ, フォロー)',
+ cRed: 'あか (キャンセル)',
+ cOrange: 'オレンジ (おきにいり)',
+ cGreen: 'みどり (リピート)',
btnRadius: 'ボタン',
+ inputRadius: 'Input fields',
panelRadius: 'パネル',
avatarRadius: 'アバター',
- avatarAltRadius: 'アバター (通知)',
+ avatarAltRadius: 'アバター (つうち)',
tooltipRadius: 'ツールチップ/アラート',
attachmentRadius: 'ファイル',
filtering: 'フィルタリング',
- filtering_explanation: 'これらの単語を含むすべてのものがミュートされます。1行に1つの単語を入力してください。',
+ filtering_explanation: 'これらのことばをふくむすべてのものがミュートされます。1行に1つのことばをかいてください。',
attachments: 'ファイル',
- hide_attachments_in_tl: 'タイムラインのファイルを隠す。',
- hide_attachments_in_convo: '会話の中のファイルを隠す。',
- nsfw_clickthrough: 'NSFWファイルの非表示を有効にする。',
- stop_gifs: 'カーソルを重ねた時にGIFを再生する。',
- autoload: '下にスクロールした時に自動で読み込むようにする。',
- streaming: '上までスクロールした時に自動でストリーミングされるようにする。',
- reply_link_preview: 'マウスカーソルを重ねた時に返信のプレビューを表示するようにする。',
+ hide_attachments_in_tl: 'タイムラインのファイルをかくす。',
+ hide_attachments_in_convo: 'スレッドのファイルをかくす。',
+ nsfw_clickthrough: 'NSFWなファイルをかくす。',
+ stop_gifs: 'カーソルをかさねたとき、GIFをうごかす。',
+ autoload: 'したにスクロールしたとき、じどうてきによみこむ。',
+ streaming: 'うえまでスクロールしたとき、じどうてきにストリーミングする。',
+ reply_link_preview: 'カーソルをかさねたとき、リプライのプレビューをみる。',
follow_import: 'フォローインポート',
import_followers_from_a_csv_file: 'CSVファイルからフォローをインポートする。',
- follows_imported: 'フォローがインポートされました!処理に少し時間がかかるかもしれません。',
- follow_import_error: 'フォロワーのインポート中にエラーが発生しました。'
+ follows_imported: 'フォローがインポートされました! すこしじかんがかかるかもしれません。',
+ follow_import_error: 'フォローのインポートがエラーになりました。',
+ delete_account: 'アカウントをけす',
+ delete_account_description: 'あなたのアカウントとメッセージが、きえます。',
+ delete_account_instructions: 'ほんとうにアカウントをけしてもいいなら、パスワードをかいてください。',
+ delete_account_error: 'アカウントをけすことが、できなかったかもしれません。インスタンスのかんりしゃに、れんらくしてください。',
+ follow_export: 'フォローのエクスポート',
+ follow_export_processing: 'おまちください。まもなくファイルをダウンロードできます。',
+ follow_export_button: 'エクスポート',
+ change_password: 'パスワードをかえる',
+ current_password: 'いまのパスワード',
+ new_password: 'あたらしいパスワード',
+ confirm_new_password: 'あたらしいパスワードのかくにん',
+ changed_password: 'パスワードが、かわりました!',
+ change_password_error: 'パスワードをかえることが、できなかったかもしれません。',
+ lock_account_description: 'あなたがみとめたひとだけ、あなたのアカウントをフォローできます。'
},
notifications: {
- notifications: '通知',
- read: '読んだ!',
+ notifications: 'つうち',
+ read: 'よんだ!',
followed_you: 'フォローされました',
- favorited_you: 'あなたの投稿がお気に入りされました',
- repeated_you: 'あなたの投稿がリピートされました'
+ favorited_you: 'あなたのステータスがおきにいりされました',
+ repeated_you: 'あなたのステータスがリピートされました'
},
login: {
login: 'ログイン',
- username: 'ユーザー名',
- placeholder: '例えば lain',
+ username: 'ユーザーめい',
+ placeholder: 'れい: lain',
password: 'パスワード',
- register: '登録',
+ register: 'はじめる',
logout: 'ログアウト'
},
registration: {
- registration: '登録',
- fullname: '表示名',
+ registration: 'はじめる',
+ fullname: 'スクリーンネーム',
email: 'Eメール',
bio: 'プロフィール',
- password_confirm: 'パスワードの確認'
+ password_confirm: 'パスワードのかくにん'
},
post_status: {
- posting: '投稿',
- default: 'ちょうどL.A.に着陸しました。'
+ posting: 'とうこう',
+ content_warning: 'せつめい (かかなくてもよい)',
+ default: 'はねだくうこうに、つきました。',
+ account_not_locked_warning: 'あなたのアカウントは {0} ではありません。あなたをフォローすれば、だれでも、フォロワーげんていのステータスをよむことができます。',
+ account_not_locked_warning_link: 'ロックされたアカウント',
+ direct_warning: 'このステータスは、メンションされたユーザーだけが、よむことができます。',
+ scope: {
+ public: 'パブリック - パブリックタイムラインにとどきます。',
+ unlisted: 'アンリステッド - パブリックタイムラインにとどきません。',
+ private: 'フォロワーげんてい - フォロワーのみにとどきます。',
+ direct: 'ダイレクト - メンションされたユーザーのみにとどきます。'
+ }
},
finder: {
- find_user: 'ユーザー検索',
- error_fetching_user: 'ユーザー検索でエラーが発生しました'
+ find_user: 'ユーザーをさがす',
+ error_fetching_user: 'ユーザーけんさくがエラーになりました。'
},
general: {
- submit: '送信',
- apply: '適用'
+ submit: 'そうしん',
+ apply: 'てきよう'
},
user_profile: {
timeline_title: 'ユーザータイムライン'
+ },
+ who_to_follow: {
+ who_to_follow: 'おすすめユーザー',
+ more: 'くわしく'
}
}
@@ -1595,6 +1634,8 @@ const ru = {
set_new_profile_background: 'Загрузить новый фон профиля',
settings: 'Настройки',
theme: 'Тема',
+ export_theme: 'Экспортировать текущую тему',
+ import_theme: 'Загрузить сохранённую тему',
presets: 'Пресеты',
theme_help: 'Используйте шестнадцатеричные коды цветов (#rrggbb) для настройки темы.',
radii_help: 'Округление краёв элементов интерфейса (в пикселях)',
@@ -1643,7 +1684,12 @@ const ru = {
confirm_new_password: 'Подтверждение нового пароля',
changed_password: 'Пароль изменён успешно.',
change_password_error: 'Произошла ошибка при попытке изменить пароль.',
- limited_availability: 'Не доступно в вашем браузере'
+ lock_account_description: 'Аккаунт доступен только подтверждённым подписчикам',
+ limited_availability: 'Не доступно в вашем браузере',
+ profile_tab: 'Профиль',
+ security_tab: 'Безопасность',
+ data_import_export_tab: 'Импорт / Экспорт данных',
+ collapse_subject: 'Сворачивать посты с темой'
},
notifications: {
notifications: 'Уведомления',
diff --git a/src/main.js b/src/main.js
index d4fbaa7b..87dc49df 100644
--- a/src/main.js
+++ b/src/main.js
@@ -49,6 +49,7 @@ const persistedStateOptions = {
'config.hideAttachments',
'config.hideAttachmentsInConv',
'config.hideNsfw',
+ 'config.replyVisibility',
'config.autoLoad',
'config.hoverPreview',
'config.streaming',
@@ -192,3 +193,12 @@ window.fetch('/instance/panel.html')
.then((html) => {
store.dispatch('setOption', { name: 'instanceSpecificPanelContent', value: html })
})
+
+window.fetch('/nodeinfo/2.0.json')
+ .then((res) => res.json())
+ .then((data) => {
+ const suggestions = data.metadata.suggestions
+ store.dispatch('setOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
+ store.dispatch('setOption', { name: 'suggestionsWeb', value: suggestions.web })
+ })
+
diff --git a/src/modules/config.js b/src/modules/config.js
index 60210a95..45bb1465 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -15,6 +15,7 @@ const defaultState = {
hoverPreview: true,
pauseOnUnfocused: true,
stopGifs: false,
+ replyVisibility: 'all',
muteWords: [],
highlight: {}
}
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 1cb5e0b8..92013448 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -37,6 +37,7 @@ const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
const FOLLOW_REQUESTS_URL = '/api/pleroma/friend_requests'
const APPROVE_USER_URL = '/api/pleroma/friendships/approve'
const DENY_USER_URL = '/api/pleroma/friendships/deny'
+const SUGGESTIONS_URL = '/api/v1/suggestions'
import { each, map } from 'lodash'
import 'whatwg-fetch'
@@ -454,6 +455,12 @@ const fetchMutes = ({credentials}) => {
}).then((data) => data.json())
}
+const suggestions = ({credentials}) => {
+ return fetch(SUGGESTIONS_URL, {
+ headers: authHeaders(credentials)
+ }).then((data) => data.json())
+}
+
const apiService = {
verifyCredentials,
fetchTimeline,
@@ -487,7 +494,8 @@ const apiService = {
changePassword,
fetchFollowRequests,
approveUser,
- denyUser
+ denyUser,
+ suggestions
}
export default apiService