Merge branch 'master' of github.com:hackersanddesigners/chatty-pub

merge with hrk
This commit is contained in:
كارل مبارك 2021-07-09 09:44:15 +02:00
commit 63bbd523c7
6 changed files with 146 additions and 65 deletions

View file

@ -1,43 +1,44 @@
<template> <template>
<div :class="[ 'body', topic.title ]"> <div :class="['body', topic.title]">
<h3 <h3 @click="desiresContent = !desiresContent" class="header">
@click="desiresContent = !desiresContent" <span class="expandToggle" v-html="toggleSymbol"></span>
class="header"
>
<span class="expandToggle">{{ desiresContent ? '▼ ' : '► '}}</span>
<span>{{ topic.title }}</span> <span>{{ topic.title }}</span>
</h3> </h3>
<div v-if="desiresContent"> <div v-if="desiresContent || print">
<span <span v-for="message in topic.messages" :key="message.id">
v-for="message in topic.messages" <Message :message="message" :show_message_data="show_message_data" />
:key="message.id"
>
<Message
:message="message"
/>
<span>&nbsp;</span> <span>&nbsp;</span>
</span> </span>
</div> </div>
<div style="float: none"><div style="page-break-after: always"></div></div>
</div> </div>
</template> </template>
<script> <script>
import Message from './Message' import Message from "./Message";
export default { export default {
name: 'Chapter', name: "Chapter",
components: { components: {
Message, Message,
}, },
data() { data() {
return { return {
desiresContent: false, desiresContent: false,
} };
}, },
props: [ props: ["topic", "print", "show_message_data"],
'topic', computed: {
], toggleSymbol() {
} let r = "";
if (!this.print) {
r = this.desiresContent ? "▼ " : "► ";
}
return r;
},
},
};
</script> </script>
<style scoped> <style scoped>
@ -45,6 +46,8 @@ export default {
cursor: pointer; cursor: pointer;
} }
@media print { @media print {
.title { display: none; } .title {
display: none;
}
} }
</style> </style>

View file

@ -1,22 +1,39 @@
<template> <template>
<span :class="classes" class="message"> <div class="message-outer">
<div class="message-data" v-if="show_message_data">
<div class="from">{{ message.sender_full_name }}</div>
<div class="time">{{ time }}</div>
</div>
<div :class="classes" class="message">
<vue3-markdown-it :source="content" v-bind="$mdOpts"></vue3-markdown-it> <vue3-markdown-it :source="content" v-bind="$mdOpts"></vue3-markdown-it>
<div class="reactions"> </div>
<div class="message-data-reactions" v-if="show_message_data">
<span
class="reaction"
v-for="reaction in message.reactions"
:key="reaction"
>
{{ String.fromCodePoint("0x" + reaction.emoji_code) }}
</span>
</div>
<div class="reactions ui">
<template v-for="reaction in reactions" :key="reaction"> <template v-for="reaction in reactions" :key="reaction">
{{ reaction }} {{ reaction }}
</template> </template>
</div> </div>
</span> </div>
</template> </template>
<script> <script>
import emoji from "../../mixins/emoji";
var EmojiConvertor = require("emoji-js"); var EmojiConvertor = require("emoji-js");
var emojiConv = new EmojiConvertor(); var emojiConv = new EmojiConvertor();
/*eslint no-unused-vars: "off"*/ /*eslint no-unused-vars: "off"*/
/*eslint no-undef: "off"*/ /*eslint no-undef: "off"*/
export default { export default {
name: "Message", name: "Message",
props: ["message"], props: ["message", "show_message_data"],
mixins: [emoji],
computed: { computed: {
rawJSON() { rawJSON() {
return "```json\n" + JSON.stringify(this.message, null, 2) + "\n```"; return "```json\n" + JSON.stringify(this.message, null, 2) + "\n```";
@ -27,8 +44,8 @@ export default {
c = c.replaceAll('src="', 'src="' + url); c = c.replaceAll('src="', 'src="' + url);
c = c.replaceAll('href="/', 'href="' + url + "/"); c = c.replaceAll('href="/', 'href="' + url + "/");
const referrers = this.$store.state const referrers = this.$store.state.topics
.topics.find(t => t.title == this.message.subject) .find((t) => t.title == this.message.subject)
.messages.filter( .messages.filter(
(m) => (m) =>
m.responseTo && m.responseTo &&
@ -58,6 +75,12 @@ export default {
classes() { classes() {
return this.message.reactions.map((r) => "u" + r.emoji_code); return this.message.reactions.map((r) => "u" + r.emoji_code);
}, },
time() {
var ts = this.message.timestamp;
var ts_ms = ts * 1000;
var date_ob = new Date(ts_ms);
return date_ob.toLocaleString();
},
}, },
created() { created() {
// console.log(this.message.content); // console.log(this.message.content);
@ -82,6 +105,7 @@ export default {
justify-content: center; justify-content: center;
background-color: rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.5);
font-size: 3rem; font-size: 3rem;
pointer-events: none;
} }
.reactions, .reactions,
.reactions::before, .reactions::before,
@ -89,4 +113,19 @@ export default {
all: revert; all: revert;
display: none; display: none;
} }
.message-data {
display: flex;
border-bottom: 1px solid #666;
}
.message-data > div {
flex-grow: 1;
}
.message-data .from:after {
content: ":";
}
.message-data .time {
text-align: right;
}
</style> </style>

View file

@ -1,17 +1,19 @@
<template> <template>
<section :class="['content', currentStream]"> <section :class="['content', currentStream]">
<h1 class="title"> {{ currentStream.replace('pub-', '') }} </h1> <h1 class="title">{{ currentStream.replace("pub-", "") }}</h1>
<Chapter <Chapter
v-for="topic in sortedTopics" v-for="topic in sortedTopics"
:key="topic.title" :key="topic.title"
:topic="topic" :topic="topic"
:print="print"
:show_message_data="show_message_data"
/> />
</section> </section>
</template> </template>
<script> <script>
import { mapGetters, mapState } from "vuex"; import { mapGetters, mapState } from "vuex";
import Chapter from './Chapter.vue'; import Chapter from "./Chapter.vue";
export default { export default {
name: "Content", name: "Content",
@ -23,6 +25,7 @@ export default {
...mapGetters(["sortedTopics"]), ...mapGetters(["sortedTopics"]),
}, },
methods: {}, methods: {},
props: ["print", "show_message_data"],
}; };
</script> </script>

View file

@ -1,29 +1,31 @@
<script> <script>
import { mapState } from 'vuex'; 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: {
...mapState([ ...mapState(["rules"]),
'rules'
]),
}, },
data() { data() {
return { return {
el: null, el: null,
} };
}, },
methods: { methods: {
generateStyleRules() { generateStyleRules() {
let styles = ""; let styles = "";
this.rules.map((r) => { this.rules.map((r) => {
styles += `.${r.parentClassName} ${r.className}` if (r.className.startsWith("@")) {
styles += r.className;
} else {
styles += `.${r.parentClassName} ${r.className}`;
if (this.containsEmoji(r.className)) { if (this.containsEmoji(r.className)) {
styles += `, .${r.parentClassName} .u${this.toEmojiCode(r.className)}` styles += `, .${r.parentClassName} .u${this.toEmojiCode(
r.className
)}`;
}
} }
styles += "{"; styles += "{";
r.rules.map((s) => { r.rules.map((s) => {
@ -40,15 +42,15 @@ export default {
}, },
}, },
mounted() { mounted() {
this.el = this.createStyleElement() this.el = this.createStyleElement();
document.head.appendChild(this.el) document.head.appendChild(this.el);
}, },
watch: { watch: {
rules() { rules() {
console.log('rules!') console.log("rules!");
const newStyle = this.createStyleElement() const newStyle = this.createStyleElement();
document.head.replaceChild(newStyle, this.el) document.head.replaceChild(newStyle, this.el);
this.el = newStyle this.el = newStyle;
}, },
}, },
}; };

View file

@ -18,7 +18,7 @@
export default { export default {
methods: { methods: {
toEmojiCode: (emoji) => { toEmojiCode: (emoji) => {
console.log(emoji); // console.log(emoji);
return emoji.replace(/\p{Emoji}/gu, (m) => m.codePointAt(0).toString(16)); return emoji.replace(/\p{Emoji}/gu, (m) => m.codePointAt(0).toString(16));
}, },

View file

@ -4,13 +4,22 @@
{{ show_ui ? "Hide" : "Show" }} UI {{ show_ui ? "Hide" : "Show" }} UI
</button> </button>
<splitpanes class="default-theme"> <splitpanes class="default-theme">
<pane v-if="show_ui" size="10" min-size="5"> <pane v-if="show_ui" size="10" min-size="5" @resize="resizer">
<Streams /> <Streams />
<div class="controls">
<button @click="toggle_ui">{{ show_ui ? "Hide" : "Show" }} UI</button> <button @click="toggle_ui">{{ show_ui ? "Hide" : "Show" }} UI</button>
<button @click="print">Print</button> <button @click="print">Print</button>
<input
type="checkbox"
id="msg-data"
value="1"
v-model="show_message_data"
/>
<label for="msg-data">Show chat message data</label>
</div>
</pane> </pane>
<pane size="55"> <pane size="55">
<Content /> <Content :print="!show_ui" :show_message_data="show_message_data" />
</pane> </pane>
<pane v-if="show_ui" size="35" min-size="15"> <pane v-if="show_ui" size="35" min-size="15">
<Rules /> <Rules />
@ -41,6 +50,8 @@ export default {
data: () => { data: () => {
return { return {
show_ui: true, show_ui: true,
show_message_data: false,
panel_sizes: { 0: 10, 1: 55, 2: 35 },
}; };
}, },
computed: { computed: {
@ -49,12 +60,15 @@ export default {
}, },
}, },
methods: { methods: {
resizer(e, i) {
console.log(e, i);
},
print() { print() {
// let prev = this.show_ui; // let prev = this.show_ui;
this.toggle_ui(null, false); this.toggle_ui(null, false);
setTimeout(() => { setTimeout(() => {
window.print(); window.print();
if (prev) this.toggle_ui(null, true); // if (prev) this.toggle_ui(null, true);
}, 1000); }, 1000);
let paged = new Previewer(); let paged = new Previewer();
console.log(paged); console.log(paged);
@ -90,6 +104,11 @@ export default {
height: 100vh; height: 100vh;
} }
.controls {
display: flex;
flex-direction: column;
}
.print .pane-wrapper { .print .pane-wrapper {
height: auto; height: auto;
} }
@ -98,10 +117,25 @@ export default {
overflow: initial; overflow: initial;
} }
iframe { .print .content iframe {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
/* absolutely needed to make the page breaks work (next style) */
.print section {
display: block !important;
}
.print .body {
page-break-after: always;
border-bottom: 3px dotted green;
}
.print .body:first-of-type {
page-break-after: always;
border-bottom: 3px dotted yellow;
}
.float-btn { .float-btn {
position: fixed; position: fixed;
z-index: 1000; z-index: 1000;
@ -109,7 +143,7 @@ iframe {
@media print { @media print {
.ui { .ui {
display: none; display: none !important;
} }
} }
</style> </style>