diff --git a/src/App.js b/src/App.js index c455c18cfdeefb1a82825cdaf07b2f8f5df49628..be6548f3a0992771562fed4d721c0c2d888833d4 100644 --- a/src/App.js +++ b/src/App.js @@ -2,8 +2,9 @@ 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 WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue' import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue' +import FeaturesPanel from './components/features_panel/features_panel.vue' +import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue' import ChatPanel from './components/chat_panel/chat_panel.vue' export default { @@ -13,8 +14,9 @@ export default { NavPanel, Notifications, UserFinder, - WhoToFollowPanel, InstanceSpecificPanel, + FeaturesPanel, + WhoToFollowPanel, ChatPanel }, data: () => ({ diff --git a/src/App.scss b/src/App.scss index dd43c5caa6f2322b817f9e3525960efb779cad2c..056a235ef1916e3584ccb0733c554112171e2e98 100644 --- a/src/App.scss +++ b/src/App.scss @@ -248,6 +248,7 @@ nav { justify-content: center; flex: 0 0 auto; z-index: -1; + .mask { mask-repeat: no-repeat; mask-position: center; @@ -260,7 +261,10 @@ nav { left: 0; right: 0; } + img { + height: 100%; + object-fit: contain; display: block; flex: 0; } @@ -325,18 +329,35 @@ main-router { background-size: cover; padding: .6em .6em; text-align: left; - font-size: 1.3em; - line-height: 24px; + line-height: 28px; background-color: $fallback--btn; background-color: var(--btn, $fallback--btn); align-items: baseline; .title { flex: 1 0 auto; + font-size: 1.3em; + } + + .alert { + white-space: nowrap; + text-overflow: ellipsis; + overflow-x: hidden; } button { - height: 100%; + flex-shrink: 0; + } + + button, .alert { + // height: 100%; + line-height: 21px; + min-height: 0; + box-sizing: border-box; + margin: 0; + margin-left: .25em; + min-width: 1px; + align-self: stretch; } } diff --git a/src/App.vue b/src/App.vue index fc446c57ab6da51f21b2cc4a00ba6908b3b47173..059460f96d78d196fdb0fd32585489ccb3673db3 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,6 +28,7 @@ <user-panel></user-panel> <nav-panel></nav-panel> <instance-specific-panel v-if="showInstanceSpecificPanel"></instance-specific-panel> + <features-panel v-if="!currentUser"></features-panel> <who-to-follow-panel v-if="currentUser && suggestionsEnabled"></who-to-follow-panel> <notifications v-if="currentUser"></notifications> </div> diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index e41929fd02ae2c2ba50a1cd9bdcc52409a2d1a7b..5528fef65918ae33f0ae27d11643cf7f1d1bcd40 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -3,7 +3,7 @@ <div class="panel-heading conversation-heading"> <span class="title"> {{ $t('timeline.conversation') }} </span> <span v-if="collapsable"> - <small><a href="#" @click.prevent="$emit('toggleExpanded')">{{ $t('timeline.collapse') }}</a></small> + <a href="#" @click.prevent="$emit('toggleExpanded')">{{ $t('timeline.collapse') }}</a> </span> </div> <div class="panel-body"> diff --git a/src/components/features_panel/features_panel.js b/src/components/features_panel/features_panel.js new file mode 100644 index 0000000000000000000000000000000000000000..80f5c966f8614511ac1e6daf2dbfd8dffea13a6f --- /dev/null +++ b/src/components/features_panel/features_panel.js @@ -0,0 +1,14 @@ +const FeaturesPanel = { + computed: { + chat: function () { + return this.$store.state.config.chatAvailable && (!this.$store.state.chatDisabled) + }, + gopher: function () { return this.$store.state.config.gopherAvailable }, + whoToFollow: function () { return this.$store.state.config.suggestionsEnabled }, + mediaProxy: function () { return this.$store.state.config.mediaProxyAvailable }, + scopeOptions: function () { return this.$store.state.config.scopeOptionsEnabled }, + textlimit: function () { return this.$store.state.config.textlimit } + } +} + +export default FeaturesPanel diff --git a/src/components/features_panel/features_panel.vue b/src/components/features_panel/features_panel.vue new file mode 100644 index 0000000000000000000000000000000000000000..445143e97e4fdec764ee031227b2a67d817117e1 --- /dev/null +++ b/src/components/features_panel/features_panel.vue @@ -0,0 +1,29 @@ +<template> + <div class="features-panel"> + <div class="panel panel-default base01-background"> + <div class="panel-heading timeline-heading base02-background base04"> + <div class="title"> + {{$t('features_panel.title')}} + </div> + </div> + <div class="panel-body features-panel"> + <ul> + <li v-if="chat">{{$t('features_panel.chat')}}</li> + <li v-if="gopher">{{$t('features_panel.gopher')}}</li> + <li v-if="whoToFollow">{{$t('features_panel.who_to_follow')}}</li> + <li v-if="mediaProxy">{{$t('features_panel.media_proxy')}}</li> + <li v-if="scopeOptions">{{$t('features_panel.scope_options')}}</li> + <li>{{$t('features_panel.text_limit')}} = {{textlimit}}</li> + </ul> + </div> + </div> + </div> +</template> + +<script src="./features_panel.js" ></script> + +<style lang="scss"> + .features-panel li { + line-height: 24px; + } +</style> diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss index 4dbceedef9edc2f543581c9f2f63314adb74352f..a137ccd5ba0e3bc132975d1ddf7d0021d9dc81e7 100644 --- a/src/components/notifications/notifications.scss +++ b/src/components/notifications/notifications.scss @@ -22,10 +22,6 @@ } .loadmore-error { - min-width: 6em; - text-align: center; - padding: 0 0.25em 0 0.25em; - margin: 0; color: $fallback--fg; color: var(--fg, $fallback--fg); } diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index 559ad0169659f5bb78e27932d64765b50599eefe..42e9c65c227bb81915e869052a05cc8a58935bd2 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -90,8 +90,7 @@ </div> <div class="upload_settings" v-if="newStatus.files.length > 0"> <input type="checkbox" id="filesSensitive" v-model="newStatus.nsfw"> - <label for="filesSensitive" v-if="newStatus.nsfw">{{$t('post_status.attachments_sensitive')}}</label> - <label for="filesSensitive" v-else v-html="$t('post_status.attachments_not_sensitive')"></label> + <label for="filesSensitive">{{$t('post_status.attachments_sensitive')}}</label> </div> </form> </div> diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index de12894b8debfa37882541306b86ac4b89bd1626..8ef84b2a78cbe00d750a68a3ebd774c189cff857 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -6,21 +6,25 @@ import { filter, trim } from 'lodash' const settings = { data () { + const config = this.$store.state.config + return { - hideAttachmentsLocal: this.$store.state.config.hideAttachments, - hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv, - hideNsfwLocal: this.$store.state.config.hideNsfw, - notificationVisibilityLocal: this.$store.state.config.notificationVisibility, - 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'), - autoLoadLocal: this.$store.state.config.autoLoad, - streamingLocal: this.$store.state.config.streaming, - pauseOnUnfocusedLocal: this.$store.state.config.pauseOnUnfocused, - hoverPreviewLocal: this.$store.state.config.hoverPreview, - collapseMessageWithSubjectLocal: this.$store.state.config.collapseMessageWithSubject, - stopGifs: this.$store.state.config.stopGifs, + hideAttachmentsLocal: config.hideAttachments, + hideAttachmentsInConvLocal: config.hideAttachmentsInConv, + hideNsfwLocal: config.hideNsfw, + notificationVisibilityLocal: config.notificationVisibility, + replyVisibilityLocal: config.replyVisibility, + loopVideoLocal: config.loopVideo, + loopVideoSilentOnlyLocal: config.loopVideoSilentOnly, + muteWordsString: config.muteWords.join('\n'), + autoLoadLocal: config.autoLoad, + streamingLocal: config.streaming, + pauseOnUnfocusedLocal: config.pauseOnUnfocused, + hoverPreviewLocal: config.hoverPreview, + collapseMessageWithSubjectLocal: typeof config.collapseMessageWithSubject === 'undefined' + ? config.defaultCollapseMessageWithSubject + : config.collapseMessageWithSubject, + stopGifs: config.stopGifs, loopSilentAvailable: // Firefox Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') || diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue index e23f8bc170529c63f7f8d4e43cc11d494eaed1d6..1dcb7ce655a96d5a8abc5d60f8b36be4334fcc6e 100644 --- a/src/components/still-image/still-image.vue +++ b/src/components/still-image/still-image.vue @@ -23,6 +23,7 @@ img { width: 100%; height: 100%; + object-fit: contain; } &.animated { diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index e42c0c4bfd61af762f920c6e14714dcf7c855fdb..2dd4376a5bf1e3de7b03a0b71735125f8d424c14 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -4,12 +4,12 @@ <div class="title"> {{title}} </div> - <button @click.prevent="showNewStatuses" class="loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError"> - {{$t('timeline.show_new')}}{{newStatusCountStr}} - </button> <div @click.prevent class="loadmore-error alert error" v-if="timelineError"> {{$t('timeline.error_fetching')}} </div> + <button @click.prevent="showNewStatuses" class="loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError"> + {{$t('timeline.show_new')}}{{newStatusCountStr}} + </button> <div @click.prevent class="loadmore-text" v-if="!timeline.newStatusCount > 0 && !timelineError"> {{$t('timeline.up_to_date')}} </div> @@ -58,7 +58,6 @@ .timeline { .loadmore-text { - font-size: 14px; opacity: 0.8; background-color: transparent; color: $fallback--faint; @@ -66,11 +65,6 @@ } .loadmore-error { - font-size: 14px; - min-width: 6em; - text-align: center; - padding: 0 0.25em 0 0.25em; - margin: 0; color: $fallback--fg; color: var(--fg, $fallback--fg); } diff --git a/src/components/user_panel/user_panel.vue b/src/components/user_panel/user_panel.vue index 3d4f873da95fb360df1cf2ef115b9cb32b9910f5..2d5cb500d6db808a6734f22d39b03241d9db2562 100644 --- a/src/components/user_panel/user_panel.vue +++ b/src/components/user_panel/user_panel.vue @@ -14,8 +14,10 @@ <style lang="scss"> .user-panel { - .profile-panel-background .panel-heading { - background: transparent; - } + .profile-panel-background .panel-heading { + background: transparent; + flex-direction: column; + align-items: stretch; + } } </style> 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 6766e561b0ef1247fede42cc44b77812181d8756..ce60308f5ba92655db39d1c45dbe3dac19312c6c 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 @@ -3,9 +3,10 @@ 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) - for (cn = random; cn < users.length; cn = cn + 10) { + var index + var step = 7 + cn = Math.floor(Math.random() * step) + for (index = 0; index < 3; index++) { var user user = users[cn] var img @@ -46,11 +47,8 @@ function showWhoToFollow (panel, reply) { } }) } - index = index + 1 - if (index > 2) { - break - } } + cn = (cn + step) % users.length } function getWhoToFollow (panel) { diff --git a/src/i18n/en.json b/src/i18n/en.json index 3cdff2802ac296413448a93446296a499cb8f107..90850b343d797a9f72c4eb0857ccb4cee1dec2e1 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -2,6 +2,15 @@ "chat": { "title": "Chat" }, + "features_panel": { + "chat": "Chat", + "gopher": "Gopher", + "media_proxy": "Media proxy", + "scope_options": "Scope options", + "text_limit": "Text limit", + "title": "Features", + "who_to_follow": "Who to follow" + }, "finder": { "error_fetching_user": "Error fetching user", "find_user": "Find user" @@ -38,8 +47,7 @@ "post_status": { "account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.", "account_not_locked_warning_link": "locked", - "attachments_not_sensitive": "Attachments <strong>not</strong> marked sensitive", - "attachments_sensitive": "Attachments marked sensitive", + "attachments_sensitive": "Mark attachments as sensitive", "content_type": { "plain_text": "Plain text" }, diff --git a/src/i18n/ja.json b/src/i18n/ja.json index 442bce16cd7560cd2f41133015e350ed67cc8a04..facef5f20ccc7b3db12b771e4045a7e0bd6795dd 100644 --- a/src/i18n/ja.json +++ b/src/i18n/ja.json @@ -2,6 +2,15 @@ "chat": { "title": "ãƒãƒ£ãƒƒãƒˆ" }, + "features_panel": { + "chat": "ãƒãƒ£ãƒƒãƒˆ", + "gopher": "Gopher", + "media_proxy": "メディアプãƒã‚¯ã‚·", + "scope_options": "ã“ã†ã‹ã„ã¯ã‚“ã„", + "text_limit": "ã‚‚ã˜ã®ã‹ãš", + "title": "ゆã†ã“ã†ãªãã®ã†", + "who_to_follow": "ãŠã™ã™ã‚ユーザー" + }, "finder": { "error_fetching_user": "ユーザーã‘ã‚“ã•ããŒã‚¨ãƒ©ãƒ¼ã«ãªã‚Šã¾ã—ãŸã€‚", "find_user": "ユーザーをã•ãŒã™" diff --git a/src/main.js b/src/main.js index debd87038eb10821c253392c29c77204328a253e..75c2bab2ce14d89b81e8dc49661fc02defdd8e38 100644 --- a/src/main.js +++ b/src/main.js @@ -114,26 +114,20 @@ window.fetch('/api/statusnet/config.json') var redirectRootNoLogin = (config.redirectRootNoLogin) var redirectRootLogin = (config.redirectRootLogin) var chatDisabled = (config.chatDisabled) - var showWhoToFollowPanel = (config.showWhoToFollowPanel) - var whoToFollowProvider = (config.whoToFollowProvider) - var whoToFollowLink = (config.whoToFollowLink) var showInstanceSpecificPanel = (config.showInstanceSpecificPanel) var scopeOptionsEnabled = (config.scopeOptionsEnabled) var formattingOptionsEnabled = (config.formattingOptionsEnabled) - var collapseMessageWithSubject = (config.collapseMessageWithSubject) + var defaultCollapseMessageWithSubject = (config.collapseMessageWithSubject) 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: 'logoMask', value: logoMask }) store.dispatch('setOption', { name: 'logoMargin', value: logoMargin }) - store.dispatch('setOption', { name: 'showWhoToFollowPanel', value: showWhoToFollowPanel }) - store.dispatch('setOption', { name: 'whoToFollowProvider', value: whoToFollowProvider }) - store.dispatch('setOption', { name: 'whoToFollowLink', value: whoToFollowLink }) store.dispatch('setOption', { name: 'showInstanceSpecificPanel', value: showInstanceSpecificPanel }) store.dispatch('setOption', { name: 'scopeOptionsEnabled', value: scopeOptionsEnabled }) store.dispatch('setOption', { name: 'formattingOptionsEnabled', value: formattingOptionsEnabled }) - store.dispatch('setOption', { name: 'collapseMessageWithSubject', value: collapseMessageWithSubject }) + store.dispatch('setOption', { name: 'defaultCollapseMessageWithSubject', value: defaultCollapseMessageWithSubject }) if (chatDisabled) { store.dispatch('disableChat') } @@ -222,7 +216,12 @@ window.fetch('/instance/panel.html') window.fetch('/nodeinfo/2.0.json') .then((res) => res.json()) .then((data) => { - const suggestions = data.metadata.suggestions + const metadata = data.metadata + store.dispatch('setOption', { name: 'mediaProxyAvailable', value: data.metadata.mediaProxy }) + store.dispatch('setOption', { name: 'chatAvailable', value: data.metadata.chat }) + store.dispatch('setOption', { name: 'gopherAvailable', value: data.metadata.gopher }) + + const suggestions = metadata.suggestions store.dispatch('setOption', { name: 'suggestionsEnabled', value: suggestions.enabled }) store.dispatch('setOption', { name: 'suggestionsWeb', value: suggestions.web }) })