Merge branch 'master' of github.com:hackersanddesigners/chatty-pub
merge with hrk
This commit is contained in:
commit
63bbd523c7
6 changed files with 146 additions and 65 deletions
|
|
@ -1,43 +1,44 @@
|
|||
<template>
|
||||
<div :class="[ 'body', topic.title ]">
|
||||
<h3
|
||||
@click="desiresContent = !desiresContent"
|
||||
class="header"
|
||||
>
|
||||
<span class="expandToggle">{{ desiresContent ? '▼ ' : '► '}}</span>
|
||||
<div :class="['body', topic.title]">
|
||||
<h3 @click="desiresContent = !desiresContent" class="header">
|
||||
<span class="expandToggle" v-html="toggleSymbol"></span>
|
||||
<span>{{ topic.title }}</span>
|
||||
</h3>
|
||||
<div v-if="desiresContent">
|
||||
<span
|
||||
v-for="message in topic.messages"
|
||||
:key="message.id"
|
||||
>
|
||||
<Message
|
||||
:message="message"
|
||||
/>
|
||||
<span> </span>
|
||||
</h3>
|
||||
<div v-if="desiresContent || print">
|
||||
<span v-for="message in topic.messages" :key="message.id">
|
||||
<Message :message="message" :show_message_data="show_message_data" />
|
||||
<span> </span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style="float: none"><div style="page-break-after: always"></div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Message from './Message'
|
||||
import Message from "./Message";
|
||||
|
||||
export default {
|
||||
name: 'Chapter',
|
||||
components: {
|
||||
name: "Chapter",
|
||||
components: {
|
||||
Message,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
desiresContent: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'topic',
|
||||
],
|
||||
}
|
||||
props: ["topic", "print", "show_message_data"],
|
||||
computed: {
|
||||
toggleSymbol() {
|
||||
let r = "";
|
||||
if (!this.print) {
|
||||
r = this.desiresContent ? "▼ " : "► ";
|
||||
}
|
||||
return r;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
@ -45,6 +46,8 @@ export default {
|
|||
cursor: pointer;
|
||||
}
|
||||
@media print {
|
||||
.title { display: none; }
|
||||
.title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,22 +1,39 @@
|
|||
<template>
|
||||
<span :class="classes" class="message">
|
||||
<vue3-markdown-it :source="content" v-bind="$mdOpts"></vue3-markdown-it>
|
||||
<div class="reactions">
|
||||
<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>
|
||||
</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">
|
||||
{{ reaction }}
|
||||
</template>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import emoji from "../../mixins/emoji";
|
||||
var EmojiConvertor = require("emoji-js");
|
||||
var emojiConv = new EmojiConvertor();
|
||||
/*eslint no-unused-vars: "off"*/
|
||||
/*eslint no-undef: "off"*/
|
||||
export default {
|
||||
name: "Message",
|
||||
props: ["message"],
|
||||
props: ["message", "show_message_data"],
|
||||
mixins: [emoji],
|
||||
computed: {
|
||||
rawJSON() {
|
||||
return "```json\n" + JSON.stringify(this.message, null, 2) + "\n```";
|
||||
|
|
@ -27,15 +44,15 @@ export default {
|
|||
c = c.replaceAll('src="', 'src="' + url);
|
||||
c = c.replaceAll('href="/', 'href="' + url + "/");
|
||||
|
||||
const referrers = this.$store.state
|
||||
.topics.find(t => t.title == this.message.subject)
|
||||
.messages.filter(
|
||||
(m) =>
|
||||
m.responseTo &&
|
||||
m.responseTo.id == this.message.id &&
|
||||
m.responseTo.sender_id == this.message.sender_id &&
|
||||
this.message.content.includes(m.responseTo.quote)
|
||||
);
|
||||
const referrers = this.$store.state.topics
|
||||
.find((t) => t.title == this.message.subject)
|
||||
.messages.filter(
|
||||
(m) =>
|
||||
m.responseTo &&
|
||||
m.responseTo.id == this.message.id &&
|
||||
m.responseTo.sender_id == this.message.sender_id &&
|
||||
this.message.content.includes(m.responseTo.quote)
|
||||
);
|
||||
referrers.forEach((m) => {
|
||||
const classes = m.reactions.map((r) => "u" + r.emoji_code).join(" ");
|
||||
c = c.replace(
|
||||
|
|
@ -58,6 +75,12 @@ export default {
|
|||
classes() {
|
||||
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() {
|
||||
// console.log(this.message.content);
|
||||
|
|
@ -82,6 +105,7 @@ export default {
|
|||
justify-content: center;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
font-size: 3rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
.reactions,
|
||||
.reactions::before,
|
||||
|
|
@ -89,4 +113,19 @@ export default {
|
|||
all: revert;
|
||||
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>
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
<template>
|
||||
<section :class="['content', currentStream]">
|
||||
<h1 class="title"> {{ currentStream.replace('pub-', '') }} </h1>
|
||||
<h1 class="title">{{ currentStream.replace("pub-", "") }}</h1>
|
||||
<Chapter
|
||||
v-for="topic in sortedTopics"
|
||||
:key="topic.title"
|
||||
:topic="topic"
|
||||
:print="print"
|
||||
:show_message_data="show_message_data"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapState } from "vuex";
|
||||
import Chapter from './Chapter.vue';
|
||||
import Chapter from "./Chapter.vue";
|
||||
|
||||
export default {
|
||||
name: "Content",
|
||||
|
|
@ -23,6 +25,7 @@ export default {
|
|||
...mapGetters(["sortedTopics"]),
|
||||
},
|
||||
methods: {},
|
||||
props: ["print", "show_message_data"],
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,31 @@
|
|||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import { mapState } from "vuex";
|
||||
import emoji from "../../mixins/emoji";
|
||||
|
||||
|
||||
export default {
|
||||
name: "Styles",
|
||||
mixins: [emoji],
|
||||
computed: {
|
||||
...mapState([
|
||||
'rules'
|
||||
]),
|
||||
|
||||
...mapState(["rules"]),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
el: null,
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
generateStyleRules() {
|
||||
let styles = "";
|
||||
this.rules.map((r) => {
|
||||
styles += `.${r.parentClassName} ${r.className}`
|
||||
if (this.containsEmoji(r.className)) {
|
||||
styles += `, .${r.parentClassName} .u${this.toEmojiCode(r.className)}`
|
||||
if (r.className.startsWith("@")) {
|
||||
styles += r.className;
|
||||
} else {
|
||||
styles += `.${r.parentClassName} ${r.className}`;
|
||||
if (this.containsEmoji(r.className)) {
|
||||
styles += `, .${r.parentClassName} .u${this.toEmojiCode(
|
||||
r.className
|
||||
)}`;
|
||||
}
|
||||
}
|
||||
styles += "{";
|
||||
r.rules.map((s) => {
|
||||
|
|
@ -40,15 +42,15 @@ export default {
|
|||
},
|
||||
},
|
||||
mounted() {
|
||||
this.el = this.createStyleElement()
|
||||
document.head.appendChild(this.el)
|
||||
this.el = this.createStyleElement();
|
||||
document.head.appendChild(this.el);
|
||||
},
|
||||
watch: {
|
||||
rules() {
|
||||
console.log('rules!')
|
||||
const newStyle = this.createStyleElement()
|
||||
document.head.replaceChild(newStyle, this.el)
|
||||
this.el = newStyle
|
||||
console.log("rules!");
|
||||
const newStyle = this.createStyleElement();
|
||||
document.head.replaceChild(newStyle, this.el);
|
||||
this.el = newStyle;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
export default {
|
||||
methods: {
|
||||
toEmojiCode: (emoji) => {
|
||||
console.log(emoji);
|
||||
// console.log(emoji);
|
||||
return emoji.replace(/\p{Emoji}/gu, (m) => m.codePointAt(0).toString(16));
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,22 @@
|
|||
{{ show_ui ? "Hide" : "Show" }} UI
|
||||
</button>
|
||||
<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 />
|
||||
<button @click="toggle_ui">{{ show_ui ? "Hide" : "Show" }} UI</button>
|
||||
<button @click="print">Print</button>
|
||||
<div class="controls">
|
||||
<button @click="toggle_ui">{{ show_ui ? "Hide" : "Show" }} UI</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 size="55">
|
||||
<Content />
|
||||
<Content :print="!show_ui" :show_message_data="show_message_data" />
|
||||
</pane>
|
||||
<pane v-if="show_ui" size="35" min-size="15">
|
||||
<Rules />
|
||||
|
|
@ -41,6 +50,8 @@ export default {
|
|||
data: () => {
|
||||
return {
|
||||
show_ui: true,
|
||||
show_message_data: false,
|
||||
panel_sizes: { 0: 10, 1: 55, 2: 35 },
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -49,12 +60,15 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
resizer(e, i) {
|
||||
console.log(e, i);
|
||||
},
|
||||
print() {
|
||||
// let prev = this.show_ui;
|
||||
this.toggle_ui(null, false);
|
||||
setTimeout(() => {
|
||||
window.print();
|
||||
if (prev) this.toggle_ui(null, true);
|
||||
// if (prev) this.toggle_ui(null, true);
|
||||
}, 1000);
|
||||
let paged = new Previewer();
|
||||
console.log(paged);
|
||||
|
|
@ -90,6 +104,11 @@ export default {
|
|||
height: 100vh;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.print .pane-wrapper {
|
||||
height: auto;
|
||||
}
|
||||
|
|
@ -98,10 +117,25 @@ export default {
|
|||
overflow: initial;
|
||||
}
|
||||
|
||||
iframe {
|
||||
.print .content iframe {
|
||||
width: 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 {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
|
|
@ -109,7 +143,7 @@ iframe {
|
|||
|
||||
@media print {
|
||||
.ui {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in a new issue