prepped for more streams, vue3 store not reactive when pushing to rules array, wonky fix

This commit is contained in:
كارل مبارك 2021-07-02 22:20:08 +02:00
parent 400b2bde87
commit b8fa676e16
8 changed files with 131 additions and 82 deletions

View file

@ -2,7 +2,6 @@
<div <div
id="app" id="app"
:class="[ :class="[
stream,
{ mobile: isMobile } { mobile: isMobile }
]"> ]">
<Styles /> <Styles />
@ -34,7 +33,6 @@ export default {
return { return {
api: api, api: api,
zulipClient: null, zulipClient: null,
stream: null,
}; };
}, },
computed: { computed: {
@ -49,13 +47,11 @@ export default {
this.getStreams(); this.getStreams();
this.$router.afterEach((to) => { this.$router.afterEach((to) => {
this.$store.commit("setContents", []);
this.$store.commit("setRules", []);
this.$store.commit("setCurStream", to.path.replace("/", "")) this.$store.commit("setCurStream", to.path.replace("/", ""))
this.stream = to.path.replace("/", "") if (this.currentStream != "") {
if (this.stream != "") { this.setUpDoc(this.currentStream);
this.setUpDoc(this.stream);
} else {
this.$store.commit("setContents", []);
this.$store.commit("setRules", []);
} }
}); });
}, },
@ -64,30 +60,30 @@ export default {
checkIfMobile: () => window.innerWidth < 700, checkIfMobile: () => window.innerWidth < 700,
getStreams() { getStreams() {
api api.zulip.init().then(client => {
.zulip
.init()
.then(client => {
this.zulipClient = client this.zulipClient = client
api api.zulip.getStreams(client).then(result => {
.zulip this.$store.commit( 'setStreams',
.getStreams(client) result.streams
.then(result => { .filter(s => s.name.startsWith(this.pubStr))
this
.$store
.commit( 'setStreams',
result
.streams
.filter(s =>
s.name.startsWith(this.pubStr)
)
) )
}) })
api.zulip.listen(this.zulipClient, this.eventHandler)
}) })
}, },
setUpDoc(stream) { setUpDoc(stream) {
api.zulip.getSubs(this.zulipClient).then(result => {
if (
!result.subscriptions
.map(s => s.name)
.includes(this.currentStream)
) {
api.zulip.addSub(this.zulipClient, this.currentStream)
}
})
api.zulip.getMsgs(this.zulipClient, stream, "content").then((result) => { api.zulip.getMsgs(this.zulipClient, stream, "content").then((result) => {
for (let m = 0; m < result.messages.length; m++) { for (let m = 0; m < result.messages.length; m++) {
const message = result.messages[m] const message = result.messages[m]
@ -99,8 +95,6 @@ export default {
this.$store.commit("setRules", result.messages); this.$store.commit("setRules", result.messages);
}); });
api.zulip.listen(this.zulipClient, this.eventHandler)
}, },
eventHandler(event) { eventHandler(event) {
@ -125,7 +119,7 @@ export default {
case 'update_message': case 'update_message':
this.$store.commit('editMessage', { this.$store.commit('editMessage', {
mid: event.message_id, mid: event.message_id,
content: event.content content: event.rendered_content
}) })
break break
@ -192,17 +186,27 @@ main {
section { section {
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
margin-left: 1em; /* margin-left: 1em; */
min-width: 500px; padding: 1em;
min-width: 800px;
max-width: 800px; max-width: 800px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: scroll; overflow: scroll;
background: lightgray;
}
section p {
margin-bottom: 0;
margin-top: 0;
} }
section .title { section .title {
display: none;
font-weight: bold; font-weight: bold;
position: sticky; position: sticky;
top: 1em; top: 1em;
} }
@media print {
.title { display: none; }
}
</style> </style>

View file

@ -1,7 +1,10 @@
<template> <template>
<section class="content"> <section class="content">
<p class="title">{{ $.type.name }}</p> <p class="title">{{ $.type.name }}</p>
<div class="body"> <div
class="body"
:class="currentStream"
>
<span <span
v-for="message in contents" v-for="message in contents"
:key="message.id" :key="message.id"
@ -27,7 +30,8 @@ export default {
computed: { computed: {
...mapState([ ...mapState([
'contents', 'contents',
'rules' 'rules',
'currentStream'
]) ])
}, },
methods: { methods: {
@ -36,7 +40,11 @@ export default {
</script> </script>
<style scoped> <style scoped>
section { .content {
max-width: 700px; max-width: 700px;
background: unset;
}
@media print {
.title { display: none; }
} }
</style> </style>

View file

@ -1,12 +1,12 @@
<template> <template>
<code <div
class="rule" class="rule"
:style="rule.rules" :style="rule.rules"
> >
<p :title="toEmojiCode(rule.className)">{{ rule.className }} {</p> <p :title="toEmojiCode(rule.className)">{{ rule.className }} {</p>
<p v-for="dec in rule.rules" :key="dec">&nbsp; {{ dec }}</p> <p v-for="dec in rule.rules" :key="dec">&nbsp; {{ dec }}</p>
<p>}</p> <p>}</p>
</code> </div>
</template> </template>
<script> <script>

View file

@ -1,27 +1,20 @@
<script> <script>
import { mapState } from 'vuex';
import emoji from "../../mixins/emoji"; import emoji from "../../mixins/emoji";
export default { export default {
name: "Styles", name: "Styles",
mixins: [emoji], mixins: [emoji],
computed: { computed: {
rules() { ...mapState([
return this.$store.state.rules; 'rules'
}, ]),
}, },
data: function () { data() {
return { return {
el: null, el: null,
htmlTags: [
'section',
'p',
'a',
'span',
'code',
'ul',
'li',
'and so on'
]
} }
}, },
methods: { methods: {
@ -38,22 +31,24 @@ export default {
}); });
styles += "}"; styles += "}";
}); });
console.log(styles)
return styles; return styles;
}, },
insertStyleElement() { createStyleElement() {
var style = document.createElement("style"); var style = document.createElement("style");
style.innerText = this.generateStyleRules(); style.innerText = this.generateStyleRules();
return style; return style;
}, },
}, },
mounted: function () { mounted() {
this.el = document.head.appendChild(this.insertStyleElement()); this.el = this.createStyleElement()
document.head.appendChild(this.el)
}, },
watch: { watch: {
rules() { rules() {
let style = this.insertStyleElement(); console.log('rules!')
this.el.parentNode.replaceChild(style, this.el); const newStyle = this.createStyleElement()
document.head.replaceChild(newStyle, this.el)
this.el = newStyle
}, },
}, },
}; };

View file

@ -22,9 +22,21 @@ export default {
...mapState([ ...mapState([
'rules', 'rules',
]) ])
},
watch: {
rules() {
console.log('rules')
}
} }
} }
</script> </script>
<style scoped> <style scoped>
.rules {
max-width: unset;
}
@media print {
.rules { display: none; }
}
</style> </style>

View file

@ -21,6 +21,8 @@ export default {
</script> </script>
<style scoped> <style scoped>
div {
}
div p { div p {
margin: 0; margin: 0;
} }

View file

@ -27,7 +27,10 @@ export default {
</script> </script>
<style scoped> <style scoped>
section { .streams {
min-width: 6em; min-width: 10em;
}
@media print {
.streams { display: none; }
} }
</style> </style>

View file

@ -1,24 +1,28 @@
/*eslint no-unused-vars: "off"*/ /*eslint no-unused-vars: "off"*/
/*eslint no-undef: "off"*/ /*eslint no-undef: "off"*/
// import Vue from 'vue'
import { createStore } from 'vuex' import { createStore } from 'vuex'
import emoji from "../mixins/emoji"; import emoji from "../mixins/emoji"
import { stripHtml } from "string-strip-html"; import { stripHtml } from "string-strip-html"
var EmojiConvertor = require('emoji-js'); var EmojiConvertor = require('emoji-js');
var emojiConv = new EmojiConvertor(); var emojiConv = new EmojiConvertor();
let toCSS = (message, currentStream) => { let toCSS = (message, currentStream) => {
// console.log(message)
let className = "", let className = "",
emoji_code = "", emoji_code = "",
rules = [], rules = [],
parentClassName = currentStream parentClassName = currentStream,
id = message.id
// let regex = /[/s]?(?<selector>.+)\s*\n?{\n?(?<prop>[\s\w.~:>-]+\s*:\s*.+;?\n?)*\n?}/gm // let regex = /[/s]?(?<selector>.+)\s*\n?{\n?(?<prop>[\s\w.~:>-]+\s*:\s*.+;?\n?)*\n?}/gm
let regex = /[/s]?(?<selector>.+)\s*\n?{\n?(?<props>(.*;\n?)+)}/gm let regex = /[/s]?(?<selector>.+)\s*\n?{\n?(?<props>(.*;\n?)+)}/gm
let content = stripHtml(message.content).result; let content = stripHtml(message.content).result;
let results = content.matchAll(regex); let results = content.matchAll(regex);
results = Array.from(results); results = Array.from(results);
// console.log(results)
if (results.length > 0) { if (results.length > 0) {
className = emojiConv.replace_colons(results[0]['groups']['selector']); className = emojiConv.replace_colons(results[0]['groups']['selector']);
if (emoji.methods.containsEmoji(className)) { if (emoji.methods.containsEmoji(className)) {
@ -26,7 +30,8 @@ let toCSS = (message, currentStream) => {
} }
rules = results[0]['groups']['props'].split("\n"); rules = results[0]['groups']['props'].split("\n");
rules = rules.filter((rule) => validateRule(rule)) rules = rules.filter((rule) => validateRule(rule))
return { className, emoji_code, rules, parentClassName }; // console.log(className, emoji_code, rules, parentClassName, id)
return { className, emoji_code, rules, parentClassName, id };
} }
return null; return null;
} }
@ -84,25 +89,22 @@ export default createStore({
}, },
mutations: { mutations: {
setMobile : (state, mobile) => state.isMobile = mobile, setMobile : (state, mobile) => state.isMobile = mobile,
setStreams : (state, streams) => state.streams = streams, setStreams : (state, streams) => state.streams = streams,
setCurStream : (state, stream) => state.currentStream = stream, setCurStream : (state, stream) => state.currentStream = stream,
setContents: (state, contents) => state.contents = contents,
addMessage: (state, message) => { addMessage: (state, message) => {
if (message.content.startsWith('@_**')) { if (message.display_recipient == state.currentStream) {
handleMDReply(message) if (message.content.startsWith('@_**')) {
} else if ( handleMDReply(message)
message.content.includes('user-mention') && } else if (
message.content.includes('blockquote') message.content.includes('user-mention') &&
) { message.content.includes('blockquote')
handleHTMLReply(message) ) {
} handleHTMLReply(message)
state.contents.push(message) }
}, state.contents.push(message)
editMessage: (state, { mid, content }) => {
const message = state.contents.find(m => m.id == mid)
if (message) {
message.content = content
} }
}, },
deleteMessage: (state, mid) => { deleteMessage: (state, mid) => {
@ -123,7 +125,6 @@ export default createStore({
message.reactions.splice(message.reactions.indexOf(reaction), 1) message.reactions.splice(message.reactions.indexOf(reaction), 1)
} }
}, },
setRules: (state, rules) => { setRules: (state, rules) => {
state.rules = rules.reduce((acc, cur) => { state.rules = rules.reduce((acc, cur) => {
let rule = toCSS(cur, state.currentStream); let rule = toCSS(cur, state.currentStream);
@ -133,12 +134,35 @@ export default createStore({
return acc return acc
}, []) }, [])
}, },
addRule: (state, rule) => { addRule: (state, rule) => {
if (toCSS(rule) !== null) { if (toCSS(rule) !== null) {
state.rules.push(toCSS(rule)) state.rules.push(toCSS(rule, state.currentStream))
} }
} },
editMessage: (state, { mid, content }) => {
const message = state.contents.find(m => m.id == mid)
const rule = state.rules.find(r => r.id == mid)
if (message) {
message.content = content
if (message.content.startsWith('@_**')) {
handleMDReply(message)
} else if (
message.content.includes('user-mention') &&
message.content.includes('blockquote')
) {
handleHTMLReply(message)
}
} else if (rule) {
const newRules = [...state.rules, ...[toCSS({
id: mid, content: content,
}, state.currentStream)]]
state.rules = newRules
// state.rules[state.rules.indexOf(rule)] = toCSS({
// id: mid, content: content,
// }, state.currentStream)
}
},
}, },
@ -146,6 +170,7 @@ export default createStore({
}, },
getters: { getters: {
rules: state => state.rules
} }
}) })