using event bus
This commit is contained in:
parent
a92369b284
commit
e95b8a606d
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
|
@ -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>
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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 })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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 ? '→' : '↓' }}
|
||||
|
@ -49,11 +49,11 @@ export default {
|
|||
},
|
||||
props: {
|
||||
status: Object,
|
||||
showMedia: {
|
||||
withAccount: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
withAccount: {
|
||||
showMedia: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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>
|
||||
|
|
12
main.css
12
main.css
|
@ -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
147
main.js
|
@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue