diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/attachment/attachment.js | 2 | ||||
| -rw-r--r-- | src/components/attachment/attachment.vue | 6 | ||||
| -rw-r--r-- | src/components/flash/flash.js | 52 | ||||
| -rw-r--r-- | src/components/flash/flash.vue | 88 | ||||
| -rw-r--r-- | src/i18n/en.json | 5 | ||||
| -rw-r--r-- | src/services/file_type/file_type.service.js | 4 | ||||
| -rw-r--r-- | src/services/ruffle_service/ruffle_service.js | 40 |
7 files changed, 196 insertions, 1 deletions
diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index 5f5779a0..8849f501 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -1,4 +1,5 @@ import StillImage from '../still-image/still-image.vue' +import Flash from '../flash/flash.vue' import VideoAttachment from '../video_attachment/video_attachment.vue' import nsfwImage from '../../assets/nsfw.png' import fileTypeService from '../../services/file_type/file_type.service.js' @@ -43,6 +44,7 @@ const Attachment = { } }, components: { + Flash, StillImage, VideoAttachment }, diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 2c1c1682..f80badfd 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -117,6 +117,11 @@ <!-- eslint-enable vue/no-v-html --> </div> </div> + + <Flash + v-if="type === 'flash'" + :src="attachment.large_thumb_url || attachment.url" + /> </div> </template> @@ -172,6 +177,7 @@ } .non-gallery.attachment { + &.flash, &.video { flex: 1 0 40%; } diff --git a/src/components/flash/flash.js b/src/components/flash/flash.js new file mode 100644 index 00000000..d03384c7 --- /dev/null +++ b/src/components/flash/flash.js @@ -0,0 +1,52 @@ +import RuffleService from '../../services/ruffle_service/ruffle_service.js' +import { library } from '@fortawesome/fontawesome-svg-core' +import { + faStop, + faExclamationTriangle +} from '@fortawesome/free-solid-svg-icons' + +library.add( + faStop, + faExclamationTriangle +) + +const Flash = { + props: [ 'src' ], + data () { + return { + player: false, // can be true, "hidden", false. hidden = element exists + loaded: false, + ruffleInstance: null + } + }, + methods: { + openPlayer () { + if (this.player) return // prevent double-loading, or re-loading on failure + this.player = 'hidden' + RuffleService.getRuffle().then((ruffle) => { + const player = ruffle.newest().createPlayer() + player.config = { + letterbox: 'on' + } + const container = this.$refs.container + container.appendChild(player) + player.style.width = '100%' + player.style.height = '100%' + player.load(this.src).then(() => { + this.player = true + }).catch((e) => { + console.error('Error loading ruffle', e) + this.player = 'error' + }) + this.ruffleInstance = player + }) + }, + closePlayer () { + console.log(this.ruffleInstance) + this.ruffleInstance.remove() + this.player = false + } + } +} + +export default Flash diff --git a/src/components/flash/flash.vue b/src/components/flash/flash.vue new file mode 100644 index 00000000..d20d037b --- /dev/null +++ b/src/components/flash/flash.vue @@ -0,0 +1,88 @@ +<template> + <div class="Flash"> + <div + v-if="player === true || player === 'hidden'" + ref="container" + class="player" + :class="{ hidden: player === 'hidden' }" + /> + <button + v-if="player !== true" + class="button-unstyled placeholder" + @click="openPlayer" + > + <span + v-if="player === 'hidden'" + class="label" + > + {{ $t('general.loading') }} + </span> + <span + v-if="player === 'error'" + class="label" + > + {{ $t('general.flash_fail') }} + </span> + <span + v-else + class="label" + > + <p> + {{ $t('general.flash_content') }} + </p> + <p> + <FAIcon icon="exclamation-triangle" /> + {{ $t('general.flash_security') }} + </p> + </span> + </button> + <button + v-if="player" + class="button-unstyled hider" + @click="closePlayer" + > + <FAIcon icon="stop" /> + </button> + </div> +</template> + +<script src="./flash.js"></script> + +<style lang="scss"> +@import '../../_variables.scss'; +.Flash { + width: 100%; + height: 260px; + position: relative; + + .player { + height: 100%; + width: 100%; + } + + .hider { + top: 0; + } + + .label { + text-align: center; + flex: 1 1 0; + line-height: 1.2; + white-space: normal; + word-wrap: normal; + } + + .hidden { + display: none; + visibility: 'hidden'; + } + + .placeholder { + height: 100%; + flex: 1; + display: flex; + align-items: center; + justify-content: center; + } +} +</style> diff --git a/src/i18n/en.json b/src/i18n/en.json index 1b38e29a..aa440ac1 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -79,7 +79,10 @@ "role": { "admin": "Admin", "moderator": "Moderator" - } + }, + "flash_content": "Click to show Flash content using Ruffle (Experimental, may not work).", + "flash_security": "Note that this can be potentially dangerous since Flash content is still arbitrary code.", + "flash_fail": "Failed to load flash content, see console for details." }, "image_cropper": { "crop_picture": "Crop picture", diff --git a/src/services/file_type/file_type.service.js b/src/services/file_type/file_type.service.js index 2a046bec..5182ecd1 100644 --- a/src/services/file_type/file_type.service.js +++ b/src/services/file_type/file_type.service.js @@ -2,6 +2,10 @@ // 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(/flash/)) { + return 'flash' + } + if (mimetype.match(/text\/html/)) { return 'html' } diff --git a/src/services/ruffle_service/ruffle_service.js b/src/services/ruffle_service/ruffle_service.js new file mode 100644 index 00000000..7411dd96 --- /dev/null +++ b/src/services/ruffle_service/ruffle_service.js @@ -0,0 +1,40 @@ +const createRuffleService = () => { + let ruffleInstance = null + + const getRuffle = () => new Promise((resolve, reject) => { + if (ruffleInstance) { + resolve(ruffleInstance) + return + } + // Ruffle needs these to be set before it's loaded + // https://github.com/ruffle-rs/ruffle/issues/3952 + window.RufflePlayer = {} + window.RufflePlayer.config = { + polyfills: false, + publicPath: '/static/ruffle' + } + + // Currently it's seems like a better way of loading ruffle + // because it needs the wasm publically accessible, but it needs path to it + // and filename of wasm seems to be pseudo-randomly generated (is it a hash?) + const script = document.createElement('script') + // see webpack config, using CopyPlugin to copy it from node_modules + // provided via ruffle-mirror + script.src = '/static/ruffle/ruffle.js' + script.type = 'text/javascript' + script.onerror = (e) => { reject(e) } + script.onabort = (e) => { reject(e) } + script.oncancel = (e) => { reject(e) } + script.onload = () => { + ruffleInstance = window.RufflePlayer + resolve(ruffleInstance) + } + document.body.appendChild(script) + }) + + return { getRuffle } +} + +const RuffleService = createRuffleService() + +export default RuffleService |
