...
 
Commits (4)
......@@ -26,7 +26,7 @@ By implementing these APIs any community radio will be able to offer a Web App f
### Development and Testing Workflow
## Development and Testing Workflow
This project requires *NodeJS* and *npm*. If any of the commands below are
not available on your computer, see the [System Requirements](#system-requirements)
......
thekno (1.1.0-1) unstable; urgency=medium
* New upstream release
-- Konrad Mohrfeldt <konrad.mohrfeldt@farbdev.org> Fri, 08 Nov 2019 13:57:32 +0100
thekno (1.0.0-1) unstable; urgency=medium
* New upstream release
......
{
"name": "thekno",
"version": "1.0.0",
"version": "1.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "thekno",
"version": "1.0.0",
"version": "1.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
......
<template>
<Button v-bind="$attrs" @click.prevent="shareData" :title="label" :aria-label="label" v-if="canShare">
<template v-slot:icon>
<component :is="shareIcon"/>
</template>
<slot/>
</Button>
</template>
<script>
import { ShareIcon, Share2Icon } from 'vue-feather-icons'
import Button from './Button'
import { isIOS } from '../../util'
export default {
components: { Button },
props: {
name: String,
payload: {
type: Object,
required: true
}
},
computed: {
canShare () {
return 'share' in window.navigator
},
shareIcon () {
return isIOS ? ShareIcon : Share2Icon
},
label () {
return this.$t(this.name ? 'share_label' : 'share_label_default', [this.name])
}
},
methods: {
shareData () {
console.log(this.payload)
window.navigator.share(this.payload)
}
}
}
</script>
<i18n lang="yaml">
en:
share_label: 'Share {0}'
share_label_default: Share content
de:
share_label: '{0} teilen'
share_label_default: Inhalt teilen
</i18n>
......@@ -18,6 +18,7 @@ import PaginatorNav from './generic/PaginatorNav'
import PlayPause from './player/PlayPause'
import Search from './generic/Search'
import Section from './generic/Section'
import Share from './generic/Share'
import Spinner from './generic/Spinner'
import SpinnerArea from './generic/SpinnerArea'
import Tag from './generic/Tag'
......@@ -42,6 +43,7 @@ Vue.component('app-paginator-nav', PaginatorNav)
Vue.component('app-play-pause', PlayPause)
Vue.component('app-search', Search)
Vue.component('app-section', Section)
Vue.component('app-share', Share)
Vue.component('app-spinner', Spinner)
Vue.component('app-spinner-area', SpinnerArea)
Vue.component('app-tag', Tag)
......
export const oneOf = values => value => values.indexOf(value) !== -1
export const isIOS = /iPad|iPhone|iPod/.test(window.navigator.userAgent) && !window.MSStream
export const renderSimpleTemplateString = (str, ctx) => {
return str.replace(/\{([a-z_]+)\}/gi, (match, key) => ctx[key] || '')
}
......
......@@ -10,6 +10,7 @@
<app-like collection="recordings" :id="recording.id"/>
<app-download look="transparent" class="ml-3" :name="$t('recording_page.download_name')"
v-if="trackDownloadUrls" :files="trackDownloadUrls"/>
<app-share look="transparent" class="ml-3" :name="recording.title" :payload="shareData"/>
</div>
</app-field>
<app-auto-grid :sizes="{ md: [2, 1], lg: [2, 1], xl: [2, 1] }" :gap-modifier="2">
......@@ -79,6 +80,14 @@
omit: this.recording.id,
is_available: 1
}
},
shareData () {
const { title, description } = this.recording
return {
title,
text: description !== title ? description : null,
url: window.location.origin + this.$route.path
}
}
},
inject: ['dataSources', 'env']
......