using event bus

This commit is contained in:
sheychen 2019-04-17 12:08:30 +02:00
parent a92369b284
commit e95b8a606d
20 changed files with 179 additions and 147 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,24 +1,18 @@
<script>
import { emitErrorMixin, handleOptionsMixin } from '../core/tools'
import serviceEmiterVue from './serviceEmiter.vue'
import serviceHeaderVue from '../core/serviceHeader.vue'
import settingBooleanVue from '../core/input/settingBoolean.vue'
import settingIntVue from '../core/input/settingInt.vue'
import settingStringVue from './input/settingString.vue'
export default {
mixins: [ emitErrorMixin, handleOptionsMixin ],
extends: serviceEmiterVue,
components: {
serviceHeader: serviceHeaderVue,
settingBoolean: settingBooleanVue,
settingInt: settingIntVue,
settingString: settingStringVue
},
methods:{
passMove(move) {
this.$emit('move', move)
}
}
}
</script>

View File

@ -6,7 +6,7 @@ export default {
},
methods: {
sendChange(value) {
this.$emit('change', { name: this.id, value: value })
this.$emit('change', { key: this.id, value: value })
}
}
}

View File

@ -0,0 +1,23 @@
<script>
export default {
props: {
emit: Function
},
methods:{
emitError(err) {
this.emit('error', err)
},
saveOptions(options) {
this.emit('saveAll', options)
},
saveOption(key, value) {
this.saveOptionCouple({
key: key, value: value
})
},
saveOptionCouple(couple) {
this.emit('save', couple)
}
}
}
</script>

View File

@ -17,9 +17,12 @@ export default {
data() { return {
showSettings: false
} },
props: {
emit: Function
},
methods: {
onMove(type, direction) {
this.$emit('move', { type: type, direction: direction })
this.emit('move', { type: type, direction: direction })
},
}
}

View File

@ -1,23 +0,0 @@
export const emitErrorMixin = {
methods: {
emitError(err) {
this.$emit('error', err.toString())
}
}
}
export const handleOptionsMixin = {
methods: {
saveOptions(options) {
this.$emit('save', options)
},
setOption(name, value) {
const options = {...this.$props}
options[name] = value
this.saveOptions(options)
},
setOptionCouple(couple) {
this.setOption(couple.name, couple.value)
}
}
}

View File

@ -9,6 +9,7 @@ a.account(target="_blank" :href="account.url")
import { parseEmojisMixin } from './tools'
export default {
mixins: [ parseEmojisMixin ],
props: {
account: Object,
showMedia: {
@ -16,7 +17,6 @@ export default {
default: true
}
},
mixins: [ parseEmojisMixin ],
methods: {
avatarStyle(avatar) {
return {

View File

@ -19,12 +19,14 @@
<script>
import { timerMinin } from '../core/fromNow.vue'
import { emitErrorMixin } from '../core/tools'
import serviceEmiterVue from '../core/serviceEmiter.vue'
import statusVue from './status.vue'
import notificationVue from './notification.vue'
export default {
mixins: [ timerMinin, emitErrorMixin ],
extends: serviceEmiterVue,
mixins: [ timerMinin ],
components: {
status: statusVue,
notification: notificationVue

View File

@ -1,17 +1,17 @@
<template lang="pug">
.mastodon
service-header(@move="passMove")
service-header(:emit="emit")
template(#title)
| Mastodon:
span(v-html="parseEmojis(account.display_name, account.emojis)")
| {{ server ? '@' + server : '' }}
template(#settings)
setting-boolean(:id="'reconnect'" :title="'Reconnect'" :value="reconnect" @change="setOptionCouple")
setting-boolean(:id="'reblog'" :title="'Show reblogs'" :value="reblog" @change="setOptionCouple")
setting-boolean(:id="'reply'" :title="'Show replies'" :value="reply" @change="setOptionCouple")
setting-int(:id="'buffer'" :title="'Buffer size'" :value="buffer" @change="setOptionCouple")
setting-boolean(:id="'showMedia'" :title="'Show medias'" :value="showMedia" @change="setOptionCouple")
client(v-if="server && token" v-bind="$props" @error="emitError")
setting-boolean(:id="'reconnect'" :title="'Reconnect'" :value="reconnect" @change="saveOptionCouple")
setting-boolean(:id="'reblog'" :title="'Show reblogs'" :value="reblog" @change="saveOptionCouple")
setting-boolean(:id="'reply'" :title="'Show replies'" :value="reply" @change="saveOptionCouple")
setting-int(:id="'buffer'" :title="'Buffer size'" :value="buffer" @change="saveOptionCouple")
setting-boolean(:id="'showMedia'" :title="'Show medias'" :value="showMedia" @change="saveOptionCouple")
client(v-if="server && token" v-bind="$props")
.auth(v-else)
form(@submit.prevent="setServer")
p
@ -77,8 +77,8 @@ export default { //TODO: Use oauth
axios.get(`https://${this.newServer}/api/v1/accounts/verify_credentials`, {
headers: { Authorization: "Bearer " + this.newToken },
timeout: this.timeout
}).then(() => this.saveOptions({...this.$props,
server: this.newServer, token: this.newToken}))
}).then(() => this.saveOptions({ ...this.$props,
server: this.newServer, token: this.newToken }))
.catch(this.emitError)
}
},

View File

@ -8,7 +8,7 @@ div
a.date(target="_blank" :href="status.uri")
from-now(:date="status.created_at" :now="now")
.content
.content(:class="{ avatared: showMedia }")
template(v-if="!status.reblog")
.spoiler(v-if="status.spoiler_text" @click.stop.prevent="status.sensitive = !status.sensitive").
{{ status.spoiler_text || 'Spoiler' }} {{ status.sensitive ? '&rarr;' : '&darr;' }}
@ -49,11 +49,11 @@ export default {
},
props: {
status: Object,
showMedia: {
withAccount: {
type: Boolean,
default: true
},
withAccount: {
showMedia: {
type: Boolean,
default: true
}

View File

@ -1,12 +1,12 @@
export const parseEmojisMixin = {
methods: {
parseEmojis(text, emojis) {
for (const emoji of emojis) {
text = text.split(`:${emoji.shortcode}:`).join(
`<img draggable="false" class="icon" alt="${emoji.shortcode}" title="${emoji.shortcode}" src="${emoji.static_url}">`
)
}
return text
}
methods: {
parseEmojis(text, emojis) {
for (const emoji of emojis) {
text = text.split(`:${emoji.shortcode}:`).join(
`<img draggable="false" class="icon" alt="${emoji.shortcode}" title="${emoji.shortcode}" src="${emoji.static_url}">`
)
}
return text
}
}
}

View File

@ -1,11 +1,11 @@
<template lang="pug">
.nextcloud-news(v-show="showEmpty || unreaded.length > 0 || !server || !token || !username")
service-header(@move="passMove")
service-header(:emit="emit")
template(#title) Nextcloud News
template(#settings)
setting-int(:id="'update'" :title="'Update interval'" :value="update" @change="setOptionCouple")
setting-int(:id="'buffer'" :title="'Buffer size'" :value="buffer" @change="setOptionCouple")
setting-boolean(:id="'showEmpty'" :title="'Show empty'" :value="showEmpty" @change="setOptionCouple")
setting-int(:id="'update'" :title="'Update interval'" :value="update" @change="saveOptionCouple")
setting-int(:id="'buffer'" :title="'Buffer size'" :value="buffer" @change="saveOptionCouple")
setting-boolean(:id="'showEmpty'" :title="'Show empty'" :value="showEmpty" @change="saveOptionCouple")
.unreaded
.news(v-for="news in unreaded")
a(:href="news.url" target="_blank")
@ -102,7 +102,7 @@ export default {
axios.get(`https://${this.newServer}/index.php/apps/news/api/v1-2/folders`, {
headers: { Authorization: 'Basic ' + btoa(this.newUsername + ':' + this.newToken) },
timeout: this.timeout
}).then(() => this.saveOptions({...this.$props,
}).then(() => this.saveOptions({ ...this.$props,
server: this.newServer, token: this.newToken, username: this.newUsername }))
.catch(this.emitError)
}

View File

@ -1,11 +1,11 @@
<template lang="pug">
.openweathermap
service-header(@move="passMove")
service-header(:emit="emit")
template(#title) OpenWeatherMap
template(#settings)
setting-string(:id="'token'" :title="'Token'" :value="token" @change="setOptionCouple")
setting-int(:id="'update'" :title="'Update interval'" :value="update" @change="setOptionCouple")
setting-int(:id="'forecastLimit'" :title="'Forecast limit'" :value="forecastLimit" @change="setOptionCouple")
setting-string(:id="'token'" :title="'Token'" :value="token" @change="saveOptionCouple")
setting-int(:id="'update'" :title="'Update interval'" :value="update" @change="saveOptionCouple")
setting-int(:id="'forecastLimit'" :title="'Forecast limit'" :value="forecastLimit" @change="saveOptionCouple")
p.setting
button(@click="showAdd = true") Add city
template(v-if="weathers.length > 0 || cities.length == 0")
@ -137,14 +137,12 @@ export default {
return `${date.toLocaleDateString()} ${date.getHours()}h`
},
addCity(id) {
const options = {...this.$props}
options.cities.push({id: id})
this.saveOptions(options)
this.cities.push({ id: id })
this.saveOption('cities', this.cities)
},
removeCity(i) {
const options = {...this.$props}
options.cities.splice(i, 1)
this.saveOptions(options)
removeCity(key) {
this.cities.splice(key, 1)
this.saveOption('cities', this.cities)
}
},
created() {

View File

@ -26,9 +26,8 @@
</div>
<div id="services">
<component
v-for="(service, key) in services" :is="service.type" :key="key"
@error="addError" @save="setService(key, $event)" @move="moveService(key, $event)"
v-bind="service.options" :style="gridPos(key, service.position)"
v-for="(service, key) in services" :is="service.type" :emit="makeEmiter(key)"
:key="key" v-bind="service.options" :style="gridPos(key, service.position)"
/>
</div>
</div>

View File

@ -15,6 +15,12 @@ a {
color: #aaa;
}
input, select, button {
background-color: #333;
color: #eee;
border: 1px solid #999;
}
.icon {
width: 1em;
height: 1em;
@ -188,7 +194,11 @@ a {
}
.mastodon .client .status .content, .mastodon .client .notification .content {
margin: 0.5em 0.5em 0.5em 3.5em;
margin: .5em .5em .5em 1em;
}
.mastodon .client .status .content.avatared, .mastodon .client .notification .content.avatared {
margin-left: 3.5em;
}
.mastodon .client .status .content .reblog, .mastodon .client .notification .content .reblog {

File diff suppressed because one or more lines are too long

147
main.js
View File

@ -2,69 +2,88 @@
const servicesStorage = 'services'
var app = new Vue({
el: '#app',
data: {
showManager: false,
newService: '',
services: [],
errors: []
},
mounted() {
if (localStorage.getItem(servicesStorage)) {
try {
this.services = JSON.parse(localStorage.getItem(servicesStorage))
} catch (e) {
localStorage.removeItem(servicesStorage)
}
}
},
methods: {
addError(err) {
this.errors.push(err)
},
removeError(id) {
this.errors.splice(id, 1)
},
addService() {
// ensure they actually typed something
if (!this.newService) {
return;
}
this.services.push({
type: this.newService,
options: {}, position: {}
})
this.newService = ''
this.showManager = false
this.saveServices()
},
setService(id, options) {
this.$set(this.services, id, {
...this.services[id],
options: options
})
this.saveServices()
},
moveService(id, move) {
const service = { ...this.services[id] }
service.position[move.type] = Math.max(1, (service.position[move.type] || 1) + move.direction)
this.$set(this.services, id, service)
this.saveServices()
},
removeService(id) {
this.services.splice(id, 1)
this.saveServices()
},
saveServices() {
localStorage.setItem(servicesStorage, JSON.stringify(this.services))
this.$forceUpdate()
},
gridPos(id, position = {}) {
return {
"grid-row": `${position.x || 1} / span ${position.h || 2}`,
"grid-column": `${position.y || id*2+1} / span ${position.w || 2}`
}
}
el: '#app',
data: {
showManager: false,
newService: '',
services: [],
errors: [],
bus: new Vue()
},
mounted() {
if (localStorage.getItem(servicesStorage)) { //TODO: allow external storage
try {
this.services = JSON.parse(localStorage.getItem(servicesStorage))
} catch (e) {
localStorage.removeItem(servicesStorage)
}
}
this.bus.$on('error', this.onError)
this.bus.$on('saveAll', this.onSaveAll)
this.bus.$on('save', this.onSave)
this.bus.$on('move', this.onMove)
},
methods: {
//Errors
onError(event) {
this.addError(event.msg.toString())
},
addError(err) {
this.errors.push(err)
},
removeError(id) {
this.errors.splice(id, 1)
},
//Services
addService() {
if (!this.newService)
return
this.services.push({
type: this.newService,
options: {}, position: {}
})
this.newService = ''
this.showManager = false
this.saveServices()
},
onSave({ key, msg }) {
this.$set(this.services[key].options, msg.key, msg.value)
this.saveServices()
},
onSaveAll({ key, msg }) {
this.$set(this.services, key, {
...this.services[key],
options: msg
})
this.saveServices()
},
onMove({ key, msg }) {
this.$set(this.services[key].position, msg.type, Math.max(1,
(this.services[key].position[msg.type] || 1) + msg.direction
))
this.saveServices()
},
removeService(id) {
this.services.splice(id, 1)
this.saveServices()
},
saveServices() {
localStorage.setItem(servicesStorage, JSON.stringify(this.services))
this.$forceUpdate()
},
gridPos(id, position = {}) {
return {
"grid-row": `${position.x || 1} / span ${position.h || 2}`,
"grid-column": `${position.y || id*2+1} / span ${position.w || 2}`
}
},
makeEmiter(key) {
const self = this
return function(name, msg) {
self.bus.$emit(name, { msg: msg, key: key })
}
}
}
})

View File

@ -28,6 +28,11 @@ a
text-decoration: none
color: $noneColor
input, select, button
background-color: $backColor
color: $foreColor
border: 1px solid $halfColor
.icon
width: 1em
height: 1em
@ -123,7 +128,9 @@ a
.status, .notification
min-height: $avatarSize
.content
margin: .5em .5em .5em .5em + $avatarSize
margin: .5em .5em .5em 1em
&.avatared
margin-left: .5em + $avatarSize
.reblog
font-size: .8em
.spoiler