From 17735943d5cdde1eb852d36f1c3bb699d23f7eb6 Mon Sep 17 00:00:00 2001 From: shpuld Date: Mon, 14 Jan 2019 19:23:13 +0200 Subject: Add media viewer module and media module component, modify attachment behavior --- src/App.js | 2 ++ src/App.vue | 1 + src/components/attachment/attachment.js | 19 +++++++++-- src/components/attachment/attachment.vue | 47 ++++++++++++++++----------- src/components/media_modal/media_modal.js | 51 ++++++++++++++++++++++++++++++ src/components/media_modal/media_modal.vue | 40 +++++++++++++++++++++++ src/components/status/status.js | 10 ++++-- src/components/status/status.vue | 9 +++++- src/main.js | 4 ++- src/modules/media_viewer.js | 40 +++++++++++++++++++++++ 10 files changed, 197 insertions(+), 26 deletions(-) create mode 100644 src/components/media_modal/media_modal.js create mode 100644 src/components/media_modal/media_modal.vue create mode 100644 src/modules/media_viewer.js (limited to 'src') diff --git a/src/App.js b/src/App.js index 85df9416..83a61d39 100644 --- a/src/App.js +++ b/src/App.js @@ -6,6 +6,7 @@ import InstanceSpecificPanel from './components/instance_specific_panel/instance 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' +import MediaModal from './components/media_modal/media_modal.vue' import SideDrawer from './components/side_drawer/side_drawer.vue' import { unseenNotificationsFromStore } from './services/notification_utils/notification_utils' @@ -20,6 +21,7 @@ export default { FeaturesPanel, WhoToFollowPanel, ChatPanel, + MediaModal, SideDrawer }, data: () => ({ diff --git a/src/App.vue b/src/App.vue index feadb009..833608ea 100644 --- a/src/App.vue +++ b/src/App.vue @@ -41,6 +41,7 @@ + diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index 97c4f283..5e672ef2 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -7,7 +7,8 @@ const Attachment = { 'attachment', 'nsfw', 'statusId', - 'size' + 'size', + 'setMedia' ], data () { return { @@ -17,13 +18,17 @@ const Attachment = { loopVideo: this.$store.state.config.loopVideo, showHidden: false, loading: false, - img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img') + img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img'), + modalOpen: false } }, components: { StillImage }, computed: { + usePlaceHolder () { + return this.size === 'hide' || this.type === 'unknown' + }, type () { return fileTypeService.fileType(this.attachment.mimetype) }, @@ -37,7 +42,7 @@ const Attachment = { return this.size === 'small' }, fullwidth () { - return fileTypeService.fileType(this.attachment.mimetype) === 'html' + return this.type === 'html' || this.type === 'audio' } }, methods: { @@ -62,6 +67,14 @@ const Attachment = { this.showHidden = !this.showHidden } }, + toggleModal (event) { + if (this.type !== 'image' && this.type !== 'video') { + return + } + event.preventDefault() + this.setMedia() + this.$store.dispatch('setCurrent', this.attachment) + }, onVideoDataLoad (e) { if (typeof e.srcElement.webkitAudioDecodedByteCount !== 'undefined') { // non-zero if video has audio track diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 5eaa0d1d..1c6b84df 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -1,19 +1,29 @@ diff --git a/src/modules/media_viewer.js b/src/modules/media_viewer.js index 27714bae..a24b408d 100644 --- a/src/modules/media_viewer.js +++ b/src/modules/media_viewer.js @@ -28,7 +28,6 @@ const mediaViewer = { }, setCurrent ({ commit, state }, current) { const index = state.media.indexOf(current) - console.log(index, current) commit('setCurrent', index || 0) }, closeMediaViewer ({ commit }) { -- cgit v1.2.3-70-g09d2 From 485a061287149fe0ff5c4a188d21d775ff271f6d Mon Sep 17 00:00:00 2001 From: shpuld Date: Sun, 20 Jan 2019 12:46:11 +0200 Subject: Polish for videos, smaller sizes, remove gif-looping options --- src/assets/nsfw.png | Bin 17071 -> 39603 bytes src/components/attachment/attachment.js | 39 +---------------- src/components/attachment/attachment.vue | 67 ++++++++++++++++++++--------- src/components/media_modal/media_modal.js | 28 ++---------- src/components/media_modal/media_modal.vue | 1 - src/components/settings/settings.js | 13 +----- src/components/settings/settings.vue | 9 ---- static/font/config.json | 12 ++++++ static/font/css/fontello-codes.css | 2 + static/font/css/fontello-embedded.css | 14 +++--- static/font/css/fontello-ie7-codes.css | 2 + static/font/css/fontello-ie7.css | 2 + static/font/css/fontello.css | 16 ++++--- static/font/demo.html | 20 +++++---- static/font/font/fontello.eot | Bin 16780 -> 17472 bytes static/font/font/fontello.svg | 6 ++- static/font/font/fontello.ttf | Bin 16612 -> 17304 bytes static/font/font/fontello.woff | Bin 10228 -> 10572 bytes static/font/font/fontello.woff2 | Bin 8692 -> 8932 bytes 19 files changed, 104 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/assets/nsfw.png b/src/assets/nsfw.png index 42749033..972bcb4c 100644 Binary files a/src/assets/nsfw.png and b/src/assets/nsfw.png differ diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index 5e672ef2..2698fb67 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -15,10 +15,7 @@ const Attachment = { nsfwImage: this.$store.state.config.nsfwCensorImage || nsfwImage, hideNsfwLocal: this.$store.state.config.hideNsfw, preloadImage: this.$store.state.config.preloadImage, - loopVideo: this.$store.state.config.loopVideo, - showHidden: false, loading: false, - img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img'), modalOpen: false } }, @@ -33,7 +30,7 @@ const Attachment = { return fileTypeService.fileType(this.attachment.mimetype) }, hidden () { - return this.nsfw && this.hideNsfwLocal && !this.showHidden + return this.nsfw && this.hideNsfwLocal }, isEmpty () { return (this.type === 'html' && !this.attachment.oembed) || this.type === 'unknown' @@ -51,46 +48,14 @@ const Attachment = { window.open(target.href, '_blank') } }, - toggleHidden () { - if (this.img && !this.preloadImage) { - if (this.img.onload) { - this.img.onload() - } else { - this.loading = true - this.img.src = this.attachment.url - this.img.onload = () => { - this.loading = false - this.showHidden = !this.showHidden - } - } - } else { - this.showHidden = !this.showHidden - } - }, toggleModal (event) { if (this.type !== 'image' && this.type !== 'video') { return } + event.stopPropagation() event.preventDefault() this.setMedia() this.$store.dispatch('setCurrent', this.attachment) - }, - 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 - } - } } } } diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 1c6b84df..74993fd9 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -4,16 +4,15 @@
- - + + + -
- Hide -
+ - + + + + @@ -44,13 +50,17 @@ diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index 7f10589c..14ae19d4 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -1,9 +1,11 @@ import StillImage from '../still-image/still-image.vue' +import VideoAttachment from '../video_attachment/video_attachment.vue' import fileTypeService from '../../services/file_type/file_type.service.js' const MediaModal = { components: { - StillImage + StillImage, + VideoAttachment }, computed: { showing () { @@ -17,9 +19,6 @@ const MediaModal = { }, type () { return this.currentMedia ? fileTypeService.fileType(this.currentMedia.mimetype) : null - }, - loopVideo () { - return this.$store.state.config.loopVideo } }, created () { diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index eb8fca53..796d4e40 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -1,14 +1,13 @@ @@ -18,7 +17,7 @@ @import '../../_variables.scss'; .modal-view { - z-index: 1005; + z-index: 1000; position: fixed; width: 100vw; height: 100vh; diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue index 25c1a9d0..a3ba14d1 100644 --- a/src/components/registration/registration.vue +++ b/src/components/registration/registration.vue @@ -215,7 +215,7 @@ $validations-cRed: #f04124; } } -@media all and (max-width: 959px) { +@media all and (max-width: 800px) { .registration-form .container { flex-direction: column-reverse; } diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index 76b42bab..06011e7c 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -13,6 +13,7 @@ const settings = { hideAttachmentsLocal: user.hideAttachments, hideAttachmentsInConvLocal: user.hideAttachmentsInConv, hideNsfwLocal: user.hideNsfw, + useOneClickNsfw: user.useOneClickNsfw, hideISPLocal: user.hideISP, preloadImage: user.preloadImage, @@ -56,7 +57,17 @@ const settings = { scopeCopyDefault: this.$t('settings.values.' + instance.scopeCopy), stopGifs: user.stopGifs, - webPushNotificationsLocal: user.webPushNotifications + webPushNotificationsLocal: user.webPushNotifications, + loopVideoSilentOnlyLocal: user.loopVideosSilentOnly, + 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'), + playVideosInline: user.playVideosInline, + useContainFit: user.useContainFit } }, components: { @@ -88,6 +99,9 @@ const settings = { hideNsfwLocal (value) { this.$store.dispatch('setOption', { name: 'hideNsfw', value }) }, + useOneClickNsfw (value) { + this.$store.dispatch('setOption', { name: 'useOneClickNsfw', value }) + }, preloadImage (value) { this.$store.dispatch('setOption', { name: 'preloadImage', value }) }, @@ -112,6 +126,9 @@ const settings = { loopVideoLocal (value) { this.$store.dispatch('setOption', { name: 'loopVideo', value }) }, + loopVideoSilentOnlyLocal (value) { + this.$store.dispatch('setOption', { name: 'loopVideoSilentOnly', value }) + }, autoLoadLocal (value) { this.$store.dispatch('setOption', { name: 'autoLoad', value }) }, @@ -146,6 +163,12 @@ const settings = { webPushNotificationsLocal (value) { this.$store.dispatch('setOption', { name: 'webPushNotifications', value }) if (value) this.$store.dispatch('registerPushNotifications') + }, + playVideosInline (value) { + this.$store.dispatch('setOption', { name: 'playVideosInline', value }) + }, + useContainFit (value) { + this.$store.dispatch('setOption', { name: 'useContainFit', value }) } } } diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index e84bd3f6..08d659d6 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -123,6 +123,10 @@ +
  • + + +
  • @@ -131,6 +135,23 @@
  • +
      +
    • + + +
      + ! {{$t('settings.limited_availability')}} +
      +
    • +
    +
  • +
  • + + +
  • +
  • + +
  • diff --git a/src/components/status/status.js b/src/components/status/status.js index 6e82307a..1db074e2 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -5,9 +5,11 @@ import DeleteButton from '../delete_button/delete_button.vue' import PostStatusForm from '../post_status_form/post_status_form.vue' import UserCardContent from '../user_card_content/user_card_content.vue' import StillImage from '../still-image/still-image.vue' +import Gallery from '../gallery/gallery.vue' import { filter, find } from 'lodash' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' +import fileType from 'src/services/file_type/file_type.service' const Status = { name: 'Status', @@ -197,6 +199,24 @@ const Status = { return 'small' } return 'normal' + }, + galleryTypes () { + if (this.attachmentSize === 'hide') { + return [] + } + return this.$store.state.config.playVideosInline + ? ['image'] + : ['image', 'video'] + }, + galleryAttachments () { + return this.status.attachments.filter( + file => fileType.fileMatchesSomeType(this.galleryTypes, file) + ) + }, + nonGalleryAttachments () { + return this.status.attachments.filter( + file => !fileType.fileMatchesSomeType(this.galleryTypes, file) + ) } }, components: { @@ -206,7 +226,8 @@ const Status = { DeleteButton, PostStatusForm, UserCardContent, - StillImage + StillImage, + Gallery }, methods: { visibilityIcon (visibility) { @@ -283,7 +304,7 @@ const Status = { return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames) }, setMedia () { - const attachments = this.status.attachments + const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments return () => this.$store.dispatch('setMedia', attachments) } }, diff --git a/src/components/status/status.vue b/src/components/status/status.vue index d7cab15b..ba3b9a4a 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -93,16 +93,23 @@ Show less -
    +
    - + :allowPlay="true" + :setMedia="setMedia()" + :key="attachment.id" + /> +
    @@ -568,7 +575,7 @@ a.unmute { } } -@media all and (max-width: 960px) { +@media all and (max-width: 800px) { .status-el { .retweet-info { .avatar { diff --git a/src/components/video_attachment/video_attachment.js b/src/components/video_attachment/video_attachment.js new file mode 100644 index 00000000..76b19a02 --- /dev/null +++ b/src/components/video_attachment/video_attachment.js @@ -0,0 +1,31 @@ + +const VideoAttachment = { + props: ['attachment', 'controls'], + data () { + return { + loopVideo: this.$store.state.config.loopVideo + } + }, + methods: { + onVideoDataLoad (e) { + const target = e.srcElement || e.target + if (typeof target.webkitAudioDecodedByteCount !== 'undefined') { + // non-zero if video has audio track + if (target.webkitAudioDecodedByteCount > 0) { + this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly + } + } else if (typeof target.mozHasAudio !== 'undefined') { + // true if video has audio track + if (target.mozHasAudio) { + this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly + } + } else if (typeof target.audioTracks !== 'undefined') { + if (target.audioTracks.length > 0) { + this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly + } + } + } + } +} + +export default VideoAttachment diff --git a/src/components/video_attachment/video_attachment.vue b/src/components/video_attachment/video_attachment.vue new file mode 100644 index 00000000..68de201e --- /dev/null +++ b/src/components/video_attachment/video_attachment.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/i18n/en.json b/src/i18n/en.json index 1dd3462b..6008287f 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -132,6 +132,7 @@ "hide_attachments_in_tl": "Hide attachments in timeline", "hide_isp": "Hide instance-specific panel", "preload_images": "Preload images", + "use_one_click_nsfw": "Open NSFW attachments with just one click", "hide_post_stats": "Hide post statistics (e.g. the number of favorites)", "hide_user_stats": "Hide user statistics (e.g. the number of followers)", "import_followers_from_a_csv_file": "Import follows from a csv file", @@ -148,6 +149,8 @@ "lock_account_description": "Restrict your account to approved followers only", "loop_video": "Loop videos", "loop_video_silent_only": "Loop only videos without sound (i.e. Mastodon's \"gifs\")", + "play_videos_inline": "Play videos directly on timeline", + "use_contain_fit": "Don't crop the attachment in thumbnails", "name": "Name", "name_bio": "Name & Bio", "new_password": "New password", diff --git a/src/i18n/fi.json b/src/i18n/fi.json index 08cfb617..969d5a9e 100644 --- a/src/i18n/fi.json +++ b/src/i18n/fi.json @@ -1,4 +1,16 @@ { + "chat": { + "title": "Chat" + }, + "features_panel": { + "chat": "Chat", + "gopher": "Gopher", + "media_proxy": "Media-välityspalvelin", + "scope_options": "Näkyvyyden rajaus", + "text_limit": "Tekstin pituusraja", + "title": "Ominaisuudet", + "who_to_follow": "Seurausehdotukset" + }, "finder": { "error_fetching_user": "Virhe hakiessa käyttäjää", "find_user": "Hae käyttäjä" @@ -9,85 +21,243 @@ }, "login": { "login": "Kirjaudu sisään", + "description": "Kirjaudu sisään OAuthilla", "logout": "Kirjaudu ulos", "password": "Salasana", - "placeholder": "esim. lain", + "placeholder": "esim. Seppo", "register": "Rekisteröidy", "username": "Käyttäjänimi" }, "nav": { + "about": "Tietoja", + "back": "Takaisin", + "chat": "Paikallinen Chat", + "friend_requests": "Seurauspyynnöt", "mentions": "Maininnat", + "dms": "Yksityisviestit", "public_tl": "Julkinen Aikajana", "timeline": "Aikajana", - "twkn": "Koko Tunnettu Verkosto" + "twkn": "Koko Tunnettu Verkosto", + "user_search": "Käyttäjähaku", + "who_to_follow": "Seurausehdotukset", + "preferences": "Asetukset" }, "notifications": { + "broken_favorite": "Viestiä ei löydetty...", "favorited_you": "tykkäsi viestistäsi", "followed_you": "seuraa sinua", + "load_older": "Lataa vanhempia ilmoituksia", "notifications": "Ilmoitukset", "read": "Lue!", "repeated_you": "toisti viestisi" }, "post_status": { + "new_status": "Uusi viesti", + "account_not_locked_warning": "Tilisi ei ole {0}. Kuka vain voi seurata sinua nähdäksesi 'vain-seuraajille' -viestisi", + "account_not_locked_warning_link": "lukittu", + "attachments_sensitive": "Merkkaa liitteet arkaluonteisiksi", + "content_type": { + "plain_text": "Tavallinen teksti" + }, + "content_warning": "Aihe (valinnainen)", "default": "Tulin juuri saunasta.", - "posting": "Lähetetään" + "direct_warning": "Tämä viesti näkyy vain mainituille käyttäjille.", + "posting": "Lähetetään", + "scope": { + "direct": "Yksityisviesti - Näkyy vain mainituille käyttäjille", + "private": "Vain-seuraajille - Näkyy vain seuraajillesi", + "public": "Julkinen - Näkyy julkisilla aikajanoilla", + "unlisted": "Listaamaton - Ei näy julkisilla aikajanoilla" + } }, "registration": { "bio": "Kuvaus", "email": "Sähköposti", "fullname": "Koko nimi", "password_confirm": "Salasanan vahvistaminen", - "registration": "Rekisteröityminen" + "registration": "Rekisteröityminen", + "token": "Kutsuvaltuus", + "captcha": "Varmenne", + "new_captcha": "Paina kuvaa saadaksesi uuden varmenteen", + "validations": { + "username_required": "ei voi olla tyhjä", + "fullname_required": "ei voi olla tyhjä", + "email_required": "ei voi olla tyhjä", + "password_required": "ei voi olla tyhjä", + "password_confirmation_required": "ei voi olla tyhjä", + "password_confirmation_match": "pitää vastata salasanaa" + } }, "settings": { + "attachmentRadius": "Liitteet", "attachments": "Liitteet", "autoload": "Lataa vanhempia viestejä automaattisesti ruudun pohjalla", "avatar": "Profiilikuva", + "avatarAltRadius": "Profiilikuvat (ilmoitukset)", + "avatarRadius": "Profiilikuvat", "background": "Tausta", "bio": "Kuvaus", + "btnRadius": "Napit", + "cBlue": "Sininen (Vastaukset, seuraukset)", + "cGreen": "Vihreä (Toistot)", + "cOrange": "Oranssi (Tykkäykset)", + "cRed": "Punainen (Peruminen)", + "change_password": "Vaihda salasana", + "change_password_error": "Virhe vaihtaessa salasanaa.", + "changed_password": "Salasana vaihdettu!", + "collapse_subject": "Minimoi viestit, joille on asetettu aihe", + "composing": "Viestien laatiminen", + "confirm_new_password": "Vahvista uusi salasana", "current_avatar": "Nykyinen profiilikuvasi", + "current_password": "Nykyinen salasana", "current_profile_banner": "Nykyinen julisteesi", + "data_import_export_tab": "Tietojen tuonti / vienti", + "default_vis": "Oletusnäkyvyysrajaus", + "delete_account": "Poista tili", + "delete_account_description": "Poista tilisi ja viestisi pysyvästi.", + "delete_account_error": "Virhe poistaessa tiliäsi. Jos virhe jatkuu, ota yhteyttä palvelimesi ylläpitoon.", + "delete_account_instructions": "Syötä salasanasi vahvistaaksesi tilin poiston.", + "export_theme": "Tallenna teema", "filtering": "Suodatus", "filtering_explanation": "Kaikki viestit, jotka sisältävät näitä sanoja, suodatetaan. Yksi sana per rivi.", + "follow_export": "Seurausten vienti", + "follow_export_button": "Vie seurauksesi CSV-tiedostoon", + "follow_export_processing": "Käsitellään, sinua pyydetään lataamaan tiedosto hetken päästä", + "follow_import": "Seurausten tuonti", + "follow_import_error": "Virhe tuodessa seuraksia", + "follows_imported": "Seuraukset tuotu! Niiden käsittely vie hetken.", "foreground": "Korostus", + "general": "Yleinen", "hide_attachments_in_convo": "Piilota liitteet keskusteluissa", "hide_attachments_in_tl": "Piilota liitteet aikajanalla", + "hide_isp": "Piilota palvelimenkohtainen ruutu", + "preload_images": "Esilataa kuvat", + "use_one_click_nsfw": "Avaa NSFW-liitteet yhdellä painalluksella", + "hide_post_stats": "Piilota viestien statistiikka (esim. tykkäysten määrä)", + "hide_user_stats": "Piilota käyttäjien statistiikka (esim. seuraajien määrä)", + "import_followers_from_a_csv_file": "Tuo seuraukset CSV-tiedostosta", + "import_theme": "Tuo tallennettu teema", + "inputRadius": "Syöttökentät", + "checkboxRadius": "Valintalaatikot", + "instance_default": "(oletus: {value})", + "instance_default_simple": "(oletus)", + "interface": "Käyttöliittymä", + "interfaceLanguage": "Käyttöliittymän kieli", + "invalid_theme_imported": "Tuotu tallennettu teema on epäkelpo, muutoksia ei tehty nykyiseen teemaasi.", + "limited_availability": "Ei saatavilla selaimessasi", "links": "Linkit", + "lock_account_description": "Vain erikseen hyväksytyt käyttäjät voivat seurata tiliäsi", + "loop_video": "Uudelleentoista videot", + "loop_video_silent_only": "Uudelleentoista ainoastaan äänettömät videot (Video-\"giffit\")", + "play_videos_inline": "Toista videot suoraan aikajanalla", + "use_contain_fit": "Älä rajaa liitteitä esikatselussa", "name": "Nimi", "name_bio": "Nimi ja kuvaus", - "nsfw_clickthrough": "Piilota NSFW liitteet klikkauksen taakse.", + "new_password": "Uusi salasana", + "notification_visibility": "Ilmoitusten näkyvyys", + "notification_visibility_follows": "Seuraukset", + "notification_visibility_likes": "Tykkäykset", + "notification_visibility_mentions": "Maininnat", + "notification_visibility_repeats": "Toistot", + "no_rich_text_description": "Älä näytä tekstin muotoilua.", + "hide_network_description": "Älä näytä seurauksiani tai seuraajiani", + "nsfw_clickthrough": "Piilota NSFW liitteet klikkauksen taakse", + "panelRadius": "Ruudut", + "pause_on_unfocused": "Pysäytä automaattinen viestien näyttö välilehden ollessa pois fokuksesta", "presets": "Valmiit teemat", "profile_background": "Taustakuva", "profile_banner": "Juliste", + "profile_tab": "Profiili", + "radii_help": "Aseta reunojen pyöristys (pikseleinä)", + "replies_in_timeline": "Keskustelut aikajanalla", "reply_link_preview": "Keskusteluiden vastauslinkkien esikatselu", + "reply_visibility_all": "Näytä kaikki vastaukset", + "reply_visibility_following": "Näytä vain vastaukset minulle tai seuraamilleni käyttäjille", + "reply_visibility_self": "Näytä vain vastaukset minulle", + "saving_err": "Virhe tallentaessa asetuksia", + "saving_ok": "Asetukset tallennettu", + "security_tab": "Tietoturva", + "scope_copy": "Kopioi näkyvyysrajaus vastatessa (Yksityisviestit aina kopioivat)", "set_new_avatar": "Aseta uusi profiilikuva", "set_new_profile_background": "Aseta uusi taustakuva", "set_new_profile_banner": "Aseta uusi juliste", "settings": "Asetukset", + "subject_input_always_show": "Näytä aihe-kenttä", + "subject_line_behavior": "Aihe-kentän kopiointi", + "subject_line_email": "Kuten sähköposti: \"re: aihe\"", + "subject_line_mastodon": "Kopioi sellaisenaan", + "subject_line_noop": "Älä kopioi", + "stop_gifs": "Toista giffit vain kohdistaessa", "streaming": "Näytä uudet viestit automaattisesti ollessasi ruudun huipulla", "text": "Teksti", "theme": "Teema", "theme_help": "Käytä heksadesimaalivärejä muokataksesi väriteemaasi.", - "user_settings": "Käyttäjän asetukset" + "theme_help_v2_1": "Voit asettaa tiettyjen osien värin tai läpinäkyvyyden täyttämällä valintalaatikon, käytä \"Tyhjennä kaikki\"-nappia tyhjentääksesi kaiken.", + "theme_help_v2_2": "Ikonit kenttien alla ovat kontrasti-indikaattoreita, lisätietoa kohdistamalla. Käyttäessä läpinäkyvyyttä ne näyttävät pahimman skenaarion.", + "tooltipRadius": "Ohje- tai huomioviestit", + "user_settings": "Käyttäjän asetukset", + "values": { + "false": "pois päältä", + "true": "päällä" + } }, "timeline": { "collapse": "Sulje", "conversation": "Keskustelu", "error_fetching": "Virhe ladatessa viestejä", "load_older": "Lataa vanhempia viestejä", + "no_retweet_hint": "Viesti ei ole julkinen, eikä sitä voi toistaa", "repeated": "toisti", "show_new": "Näytä uudet", "up_to_date": "Ajantasalla" }, "user_card": { + "approve": "Hyväksy", + "block": "Estä", + "blocked": "Estetty!", + "deny": "Älä hyväksy", "follow": "Seuraa", + "follow_sent": "Pyyntö lähetetty!", + "follow_progress": "Pyydetään...", + "follow_again": "Lähetä pyyntö uudestaan", + "follow_unfollow": "Älä seuraa", "followees": "Seuraa", "followers": "Seuraajat", "following": "Seuraat!", "follows_you": "Seuraa sinua!", + "its_you": "Sinun tili!", "mute": "Hiljennä", "muted": "Hiljennetty", "per_day": "päivässä", + "remote_follow": "Seuraa muualta", "statuses": "Viestit" + }, + "user_profile": { + "timeline_title": "Käyttäjän aikajana" + }, + "who_to_follow": { + "more": "Lisää", + "who_to_follow": "Seurausehdotukset" + }, + "tool_tip": { + "media_upload": "Lataa tiedosto", + "repeat": "Toista", + "reply": "Vastaa", + "favorite": "Tykkää", + "user_settings": "Käyttäjäasetukset" + }, + "upload":{ + "error": { + "base": "Lataus epäonnistui.", + "file_too_big": "Tiedosto liian suuri [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]", + "default": "Yritä uudestaan myöhemmin" + }, + "file_size_units": { + "B": "tavua", + "KiB": "kt", + "MiB": "Mt", + "GiB": "Gt", + "TiB": "Tt" + } } } diff --git a/src/services/file_type/file_type.service.js b/src/services/file_type/file_type.service.js index f543ec79..2a046bec 100644 --- a/src/services/file_type/file_type.service.js +++ b/src/services/file_type/file_type.service.js @@ -1,27 +1,32 @@ -const fileType = (typeString) => { - let type = 'unknown' - - if (typeString.match(/text\/html/)) { - type = 'html' +// TODO this func might as well take the entire file and use its mimetype +// or the entire service could be just mimetype service that only operates +// on mimetypes and not files. Currently the naming is confusing. +const fileType = mimetype => { + if (mimetype.match(/text\/html/)) { + return 'html' } - if (typeString.match(/image/)) { - type = 'image' + if (mimetype.match(/image/)) { + return 'image' } - if (typeString.match(/video/)) { - type = 'video' + if (mimetype.match(/video/)) { + return 'video' } - if (typeString.match(/audio/)) { - type = 'audio' + if (mimetype.match(/audio/)) { + return 'audio' } - return type + return 'unknown' } +const fileMatchesSomeType = (types, file) => + types.some(type => fileType(file.mimetype) === type) + const fileTypeService = { - fileType + fileType, + fileMatchesSomeType } export default fileTypeService diff --git a/test/unit/specs/services/file_type/file_type.spec.js b/test/unit/specs/services/file_type/file_type.spec.js new file mode 100644 index 00000000..eb8a087d --- /dev/null +++ b/test/unit/specs/services/file_type/file_type.spec.js @@ -0,0 +1,19 @@ +import fileType from 'src/services/file_type/file_type.service.js' + +describe('fileType service', () => { + describe('fileMatchesSomeType', () => { + it('should be true when file type is one of the listed', () => { + const file = { mimetype: 'audio/mpeg' } + const types = ['video', 'audio'] + + expect(fileType.fileMatchesSomeType(types, file)).to.eql(true) + }) + + it('should be false when files type is not included in type list', () => { + const file = { mimetype: 'audio/mpeg' } + const types = ['image', 'video'] + + expect(fileType.fileMatchesSomeType(types, file)).to.eql(false) + }) + }) +}) -- cgit v1.2.3-70-g09d2 From 676acdbf82726cd78ce8611d4c6ba78c58b8fc4c Mon Sep 17 00:00:00 2001 From: shpuld Date: Sat, 26 Jan 2019 17:59:59 +0200 Subject: Add default config for new options, fix firefox inline playing --- src/components/attachment/attachment.vue | 2 +- static/config.json | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 5a80db8a..7e972026 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -34,7 +34,7 @@ @click="openModal" v-if="type === 'video' && !hidden" :class="{'small': isSmall}" - :href="attachment.url" + :href="allowPlay ? undefined : attachment.url" > diff --git a/static/config.json b/static/config.json index 24e26696..aac93f70 100644 --- a/static/config.json +++ b/static/config.json @@ -19,5 +19,8 @@ "loginMethod": "password", "webPushNotifications": false, "noAttachmentLinks": false, - "nsfwCensorImage": "" + "nsfwCensorImage": "", + "useOneClickNsfw": true, + "playVideosInline": false, + "useContainFit": false } -- cgit v1.2.3-70-g09d2