Merge pull request #32 from kylejwatson/ft-toast

Ft toast
This commit is contained in:
Preston 2020-08-02 10:57:23 -04:00 committed by GitHub
commit 8576d0fddb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 2 deletions

View File

@ -1,6 +1,7 @@
import Vue from 'vue' import Vue from 'vue'
import TopNav from './components/top-nav/top-nav.vue' import TopNav from './components/top-nav/top-nav.vue'
import SideNav from './components/side-nav/side-nav.vue' import SideNav from './components/side-nav/side-nav.vue'
import FtToast from './components/ft-toast/ft-toast.vue'
import $ from 'jquery' import $ from 'jquery'
let useElectron let useElectron
@ -18,7 +19,8 @@ export default Vue.extend({
name: 'App', name: 'App',
components: { components: {
TopNav, TopNav,
SideNav SideNav,
FtToast,
}, },
computed: { computed: {
isOpen: function () { isOpen: function () {

View File

@ -14,6 +14,7 @@
/> />
<!-- </keep-alive> --> <!-- </keep-alive> -->
</Transition> </Transition>
<ft-toast />
</div> </div>
</template> </template>

View File

@ -2,6 +2,7 @@ import Vue from 'vue'
import FtIconButton from '../ft-icon-button/ft-icon-button.vue' import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
import FtButton from '../ft-button/ft-button.vue' import FtButton from '../ft-button/ft-button.vue'
import { mapActions } from 'vuex'
export default Vue.extend({ export default Vue.extend({
name: 'FtShareButton', name: 'FtShareButton',
@ -59,6 +60,7 @@ export default Vue.extend({
}, },
copyInvidious() { copyInvidious() {
this.showToast('Invidious URL copied to clipboard')
this.copy(this.invidiousURL) this.copy(this.invidiousURL)
this.$refs.iconButton.toggleDropdown() this.$refs.iconButton.toggleDropdown()
}, },
@ -69,6 +71,7 @@ export default Vue.extend({
}, },
copyYoutube() { copyYoutube() {
this.showToast('YouTube URL copied to clipboard')
this.copy(this.youtubeURL) this.copy(this.youtubeURL)
this.$refs.iconButton.toggleDropdown() this.$refs.iconButton.toggleDropdown()
}, },
@ -79,6 +82,7 @@ export default Vue.extend({
}, },
copyYoutubeEmbed() { copyYoutubeEmbed() {
this.showToast('YouTube Embed URL copied to clipboard')
this.copy(this.youtubeEmbedURL) this.copy(this.youtubeEmbedURL)
this.$refs.iconButton.toggleDropdown() this.$refs.iconButton.toggleDropdown()
}, },
@ -89,8 +93,13 @@ export default Vue.extend({
}, },
copyInvidiousEmbed() { copyInvidiousEmbed() {
this.showToast('Invidious Embed URL copied to clipboard')
this.copy(this.invidiousEmbedURL) this.copy(this.invidiousEmbedURL)
this.$refs.iconButton.toggleDropdown() this.$refs.iconButton.toggleDropdown()
}, },
...mapActions([
'showToast'
])
} }
}) })

View File

@ -0,0 +1,4 @@
import Vue from 'vue'
const events = new Vue()
export default events

View File

@ -0,0 +1,37 @@
.toast-holder {
position: fixed;
left: 50vw;
transform: translate(-50%, 0);
bottom: 50px;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.toast {
padding: 10px;
margin: 5px;
overflow-y: auto;
background-color: rgba(0, 0, 0, 0.7);
color: white;
opacity: 0;
border-radius: 20px;
cursor: pointer;
}
.message {
margin: auto;
}
.open {
visibility: visible;
opacity: 1;
transition: visibility 0s linear 0s, opacity 300ms;
}
.closed {
visibility: hidden;
opacity: 0;
transition: visibility 0s linear 300ms, opacity 300ms;
}

View File

@ -0,0 +1,42 @@
import Vue from 'vue'
import FtToastEvents from './ft-toast-events.js'
export default Vue.extend({
name: 'FtToast',
data: function () {
return {
toasts: [],
}
},
mounted: function () {
FtToastEvents.$on('toast.open', this.open)
},
beforeDestroy: function () {
FtToastEvents.$off('toast.open', this.open)
},
methods: {
performAction: function (index) {
this.toasts[index].action()
this.remove(index)
},
close: function (toast) {
// Wait for fade-out to finish
setTimeout(this.remove, 300, 0)
toast.isOpen = false
},
open: function (message, action, time) {
const toast = { message: message, action: action || (() => { }), isOpen: false, timeout: null }
toast.timeout = setTimeout(this.close, time || 3000, toast)
setImmediate(() => { toast.isOpen = true })
if (this.toasts.length > 4) {
this.remove(0)
}
this.toasts.push(toast)
},
remove: function(index) {
const removed = this.toasts.splice(index, 1)
clearTimeout(removed[0].timeout)
}
},
})

View File

@ -0,0 +1,18 @@
<template>
<div class="toast-holder">
<div
v-for="(toast, index) in toasts"
:key="'toast-' + index"
class="toast"
:class="{ closed: !toast.isOpen, open: toast.isOpen }"
@click="performAction(index)"
>
<p class="message">
{{ toast.message }}
</p>
</div>
</div>
</template>
<script src="./ft-toast.js" />
<style scoped src="./ft-toast.css" />

View File

@ -1,5 +1,5 @@
import IsEqual from 'lodash.isequal' import IsEqual from 'lodash.isequal'
import FtToastEvents from '../../components/ft-toast/ft-toast-events'
const state = { const state = {
isSideNavOpen: false, isSideNavOpen: false,
sessionSearchHistory: [], sessionSearchHistory: [],
@ -84,6 +84,10 @@ const actions = {
] ]
return extractors.reduce((a, c) => a || c(), null) || false return extractors.reduce((a, c) => a || c(), null) || false
},
showToast (_, message, action, time) {
FtToastEvents.$emit('toast.open', message, action, time)
} }
} }