Configurable video looping, option to not to loop silent videos. Updated

localization strings.
This commit is contained in:
Henry Jameson 2018-08-15 12:51:21 +03:00
parent d2ec70c323
commit 0e5b74e3dd
6 changed files with 70 additions and 7 deletions

View file

@ -13,6 +13,7 @@ const Attachment = {
return { return {
nsfwImage, nsfwImage,
hideNsfwLocal: this.$store.state.config.hideNsfw, hideNsfwLocal: this.$store.state.config.hideNsfw,
loopVideo: this.$store.state.config.loopVideo,
showHidden: false, showHidden: false,
loading: false, loading: false,
img: this.type === 'image' && document.createElement('img') img: this.type === 'image' && document.createElement('img')
@ -59,6 +60,23 @@ const Attachment = {
} else { } else {
this.showHidden = !this.showHidden this.showHidden = !this.showHidden
} }
},
onVideoDataLoad (e) {
if (typeof e.srcElement.webkitAudioDecodedByteCount !== 'undefined') {
// non-zero if video has audio track
if (e.srcElement.webkitAudioDecodedByteCount > 0) {
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
}
} else if (typeof e.srcElement.mozHasAudio !== 'undefined') {
// true if video has audio track
if (e.srcElement.mozHasAudio) {
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
}
} else if (typeof e.srcElement.audioTracks !== 'undefined') {
if (e.srcElement.audioTracks.length > 0) {
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
}
}
} }
} }
} }

View file

@ -14,7 +14,7 @@
<StillImage :class="{'small': isSmall}" referrerpolicy="no-referrer" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/> <StillImage :class="{'small': isSmall}" referrerpolicy="no-referrer" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
</a> </a>
<video :class="{'small': isSmall}" v-if="type === 'video' && !hidden" :src="attachment.url" controls loop></video> <video :class="{'small': isSmall}" v-if="type === 'video' && !hidden" @loadeddata="onVideoDataLoad" :src="attachment.url" controls :loop="loopVideo"></video>
<audio v-if="type === 'audio'" :src="attachment.url" controls></audio> <audio v-if="type === 'audio'" :src="attachment.url" controls></audio>

View file

@ -1,3 +1,4 @@
/* eslint-env browser */
import StyleSwitcher from '../style_switcher/style_switcher.vue' import StyleSwitcher from '../style_switcher/style_switcher.vue'
import { filter, trim } from 'lodash' import { filter, trim } from 'lodash'
@ -7,12 +8,21 @@ const settings = {
hideAttachmentsLocal: this.$store.state.config.hideAttachments, hideAttachmentsLocal: this.$store.state.config.hideAttachments,
hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv, hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
hideNsfwLocal: this.$store.state.config.hideNsfw, hideNsfwLocal: this.$store.state.config.hideNsfw,
loopVideoLocal: this.$store.state.config.loopVideo,
loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly,
muteWordsString: this.$store.state.config.muteWords.join('\n'), muteWordsString: this.$store.state.config.muteWords.join('\n'),
autoLoadLocal: this.$store.state.config.autoLoad, autoLoadLocal: this.$store.state.config.autoLoad,
streamingLocal: this.$store.state.config.streaming, streamingLocal: this.$store.state.config.streaming,
pauseOnUnfocused: this.$store.state.config.pauseOnUnfocused, pauseOnUnfocusedLocal: this.$store.state.config.pauseOnUnfocused,
hoverPreviewLocal: this.$store.state.config.hoverPreview, hoverPreviewLocal: this.$store.state.config.hoverPreview,
stopGifs: this.$store.state.config.stopGifs stopGifs: this.$store.state.config.stopGifs,
loopSilentAvailable:
// Firefox
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
// Chrome-likes
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
// Future spec, still not supported in Nightly 63 as of 08/2018
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks')
} }
}, },
components: { components: {
@ -33,6 +43,12 @@ const settings = {
hideNsfwLocal (value) { hideNsfwLocal (value) {
this.$store.dispatch('setOption', { name: 'hideNsfw', value }) this.$store.dispatch('setOption', { name: 'hideNsfw', value })
}, },
loopVideoLocal (value) {
this.$store.dispatch('setOption', { name: 'loopVideo', value })
},
loopVideoSilentOnlyLocal (value) {
this.$store.dispatch('setOption', { name: 'loopVideoSilentOnly', value })
},
autoLoadLocal (value) { autoLoadLocal (value) {
this.$store.dispatch('setOption', { name: 'autoLoad', value }) this.$store.dispatch('setOption', { name: 'autoLoad', value })
}, },

View file

@ -22,7 +22,7 @@
<ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]"> <ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
<li> <li>
<input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal"> <input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal">
<label for="pauseOnUnfocused">{{$t('settings.pauseOnUnfocused')}}</label> <label for="pauseOnUnfocused">{{$t('settings.pause_on_unfocused')}}</label>
</li> </li>
</ul> </ul>
</li> </li>
@ -55,6 +55,19 @@
<input type="checkbox" id="stopGifs" v-model="stopGifs"> <input type="checkbox" id="stopGifs" v-model="stopGifs">
<label for="stopGifs">{{$t('settings.stop_gifs')}}</label> <label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
</li> </li>
<li>
<input type="checkbox" id="loopVideo" v-model="loopVideoLocal">
<label for="loopVideo">{{$t('settings.loop_video')}}</label>
<ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
<li>
<input :disabled="!loopVideoLocal || !loopSilentAvailable" type="checkbox" id="loopVideoSilentOnly" v-model="loopVideoSilentOnlyLocal">
<label for="loopVideoSilentOnly">{{$t('settings.loop_video_silent_only')}}</label>
<div v-if="!loopSilentAvailable" class="unavailable">
<i class="icon-globe"/>! {{$t('settings.limited_availability')}}
</div>
</li>
</ul>
</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -78,6 +91,12 @@
height: 100px; height: 100px;
} }
.unavailable,
.unavailable i {
color: var(--cRed, $fallback--cRed);
color: $fallback--cRed;
}
.old-avatar { .old-avatar {
width: 128px; width: 128px;
border-radius: $fallback--avatarRadius; border-radius: $fallback--avatarRadius;

View file

@ -314,7 +314,9 @@ const en = {
stop_gifs: 'Play-on-hover GIFs', stop_gifs: 'Play-on-hover GIFs',
autoload: 'Enable automatic loading when scrolled to the bottom', autoload: 'Enable automatic loading when scrolled to the bottom',
streaming: 'Enable automatic streaming of new posts when scrolled to the top', streaming: 'Enable automatic streaming of new posts when scrolled to the top',
pauseOnUnfocused: 'Pause streaming when tab is not focused', pause_on_unfocused: 'Pause streaming when tab is not focused',
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_link_preview: 'Enable reply-link preview on mouse hover',
follow_import: 'Follow import', follow_import: 'Follow import',
import_followers_from_a_csv_file: 'Import follows from a csv file', import_followers_from_a_csv_file: 'Import follows from a csv file',
@ -333,7 +335,8 @@ const en = {
confirm_new_password: 'Confirm new password', confirm_new_password: 'Confirm new password',
changed_password: 'Password changed successfully!', changed_password: 'Password changed successfully!',
change_password_error: 'There was an issue changing your password.', change_password_error: 'There was an issue changing your password.',
lock_account_description: 'Restrict your account to approved followers only' lock_account_description: 'Restrict your account to approved followers only',
limited_availability: 'Unavailable in your browser'
}, },
notifications: { notifications: {
notifications: 'Notifications', notifications: 'Notifications',
@ -1606,6 +1609,9 @@ const ru = {
nsfw_clickthrough: 'Включить скрытие NSFW вложений', nsfw_clickthrough: 'Включить скрытие NSFW вложений',
autoload: 'Включить автоматическую загрузку при прокрутке вниз', autoload: 'Включить автоматическую загрузку при прокрутке вниз',
streaming: 'Включить автоматическую загрузку новых сообщений при прокрутке вверх', streaming: 'Включить автоматическую загрузку новых сообщений при прокрутке вверх',
pause_on_unfocused: 'Приостановить загрузку когда вкладка не в фокусе',
loop_video: 'Зациливать видео',
loop_video_silent_only: 'Зацикливать только беззвучные видео (т.е. "гифки" с Mastodon)',
reply_link_preview: 'Включить предварительный просмотр ответа при наведении мыши', reply_link_preview: 'Включить предварительный просмотр ответа при наведении мыши',
follow_import: 'Импортировать читаемых', follow_import: 'Импортировать читаемых',
import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv', import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv',
@ -1623,7 +1629,8 @@ const ru = {
new_password: 'Новый пароль', new_password: 'Новый пароль',
confirm_new_password: 'Подтверждение нового пароля', confirm_new_password: 'Подтверждение нового пароля',
changed_password: 'Пароль изменён успешно.', changed_password: 'Пароль изменён успешно.',
change_password_error: 'Произошла ошибка при попытке изменить пароль.' change_password_error: 'Произошла ошибка при попытке изменить пароль.',
limited_availability: 'Не доступно в вашем браузере'
}, },
notifications: { notifications: {
notifications: 'Уведомления', notifications: 'Уведомления',

View file

@ -7,9 +7,12 @@ const defaultState = {
hideAttachments: false, hideAttachments: false,
hideAttachmentsInConv: false, hideAttachmentsInConv: false,
hideNsfw: true, hideNsfw: true,
loopVideo: true,
loopVideoSilentOnly: true,
autoLoad: true, autoLoad: true,
streaming: false, streaming: false,
hoverPreview: true, hoverPreview: true,
pauseOnUnfocused: true,
muteWords: [], muteWords: [],
highlight: {} highlight: {}
} }