feat: 新增聊天表情

This commit is contained in:
kuaifan 2022-04-17 18:31:45 +08:00
parent f5b663b900
commit 8cbc3a9667
151 changed files with 11330 additions and 75 deletions

View File

@ -206,17 +206,28 @@ class WebSocketDialogMsg extends AbstractModel
*/
public static function formatMsg($text, $dialog_id)
{
// 图片
// 图片 [:IMAGE:className:width:height:src:alt:]
preg_match_all("/<img\s*src=\"data:image\/(png|jpg|jpeg);base64,(.*?)\"(.*?)>(<\/img>)*/s", $text, $matchs);
foreach ($matchs[2] as $key => $base64) {
$tmpPath = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/";
Base::makeDir(public_path($tmpPath));
$tmpPath .= md5s($base64) . "." . $matchs[1][$key];
if (file_put_contents(public_path($tmpPath), base64_decode($base64))) {
$text = str_replace($matchs[0][$key], "[:IMG:{$tmpPath}:]", $text);
$imagesize = getimagesize(public_path($tmpPath));
$text = str_replace($matchs[0][$key], "[:IMAGE:browse:{$imagesize[0]}:{$imagesize[1]}:{$tmpPath}::]", $text);
}
}
// @成员 #任务
// 表情图片
preg_match_all("/<img class=\"emoticon\"(.*?)>/s", $text, $matchs);
foreach ($matchs[1] as $key => $str) {
preg_match("/data-asset=\"(.*?)\"/", $str, $matchAsset);
preg_match("/data-name=\"(.*?)\"/", $str, $matchName);
if (file_exists(public_path($matchAsset[1]))) {
$imagesize = getimagesize(public_path($matchAsset[1]));
$text = str_replace($matchs[0][$key], "[:IMAGE:emoticon:{$imagesize[0]}:{$imagesize[1]}:{$matchAsset[1]}:{$matchName[1]}:]", $text);
}
}
// @成员、#任务
preg_match_all("/<span class=\"mention\"(.*?)>.*?<\/span>.*?<\/span>.*?<\/span>/s", $text, $matchs);
foreach ($matchs[1] as $key => $str) {
preg_match("/data-denotation-char=\"(.*?)\"/", $str, $matchChar);
@ -227,7 +238,7 @@ class WebSocketDialogMsg extends AbstractModel
// 过滤标签
$text = strip_tags($text, '<p>');
$text = preg_replace("/\<p.*?\>/i", "<p>", $text);
$text = preg_replace("/\[:IMG:(.*?):\]/i", "<img src=\"{{RemoteURL}}$1\"/>", $text);
$text = preg_replace("/\[:IMAGE:(.*?):(.*?):(.*?):(.*?):(.*?):\]/i", "<img class=\"$1\" width=\"$2\" height=\"$3\" src=\"{{RemoteURL}}$4\" alt=\"$5\"/>", $text);
$text = preg_replace("/\[:@:(.*?):(.*?):\]/i", "<span class=\"mention user\" data-id=\"$1\">@$2</span>", $text);
return preg_replace("/\[:#:(.*?):(.*?):\]/i", "<span class=\"mention task\" data-id=\"$1\">#$2</span>", $text);
}

View File

@ -69,7 +69,6 @@
"view-design-hi": "^4.7.0-20",
"vue": "^2.6.14",
"vue-clipboard2": "^0.3.3",
"vue-emoji-picker": "^1.0.3",
"vue-kityminder-ggg": "^1.3.10",
"vue-loader": "^15.9.8",
"vue-resize-observer": "^2.0.16",

View File

@ -375,6 +375,19 @@
*/
getDialogMention(dialog) {
return dialog ? (dialog.mention || 0) : 0
},
/**
* 返回文本信息预览格式
* @param text
* @returns {*}
*/
getMsgTextPreview(text) {
if (!text) return '';
text = text.replace(/<img\s+class="emoticon"[^>]*?alt="(\S+)"[^>]*?>/g, "[$1]")
text = text.replace(/<img\s+class="emoticon"[^>]*?>/g, `[${$A.L('表情')}]`)
text = text.replace(/<img\s+class="browse"[^>]*?>/g, `[${$A.L('图片')}]`)
return text.replace(/<[^>]+>/g,"")
}
});

View File

@ -898,9 +898,7 @@ export default {
let body = '';
switch (type) {
case 'text':
body = msg.text;
body = body.replace(/<img src=".*?"\/>/g, `[${this.$L('图片')}]`)
body = body.replace(/<[^>]+>/g,"")
body = $A.getMsgTextPreview(msg.text)
break;
case 'file':
body = '[' + this.$L(msg.type == 'img' ? '图片信息' : '文件信息') + ']'

View File

@ -0,0 +1,87 @@
<template>
<div class="chat-emoji-wrapper">
<ul class="chat-emoji-box overlay-y" :class="type">
<li v-for="item in list" @click="onSelect(item)">
<img v-if="item.type === 'emoticon'" :src="item.src" :title="item.name" :alt="item.name"/>
<span v-else v-html="item.html" :title="item.name"></span>
</li>
</ul>
<ul class="chat-emoji-menu">
<li :class="{active: type === 'emoji'}" @click="type='emoji'">
<span>&#128512;</span>
</li>
<li v-for="item in emoticonList" :class="{active: type === 'emoticon' && emoticonPath == item.path}" @click="onEmoticon(item.path)">
<img :title="item.name" :alt="item.name" :src="item.src"/>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'ChatEmoji',
props: {
},
data() {
return {
type: 'emoji',
emoticonPath: '',
};
},
mounted() {
},
computed: {
list() {
if (this.type === 'emoji') {
if (!$A.isArray(window.emojiData)) {
return [];
}
return window.emojiData.sort(function (a, b) {
return a.emoji_order - b.emoji_order;
}).map(item => {
return {
type: 'emoji',
name: item.name,
html: item.code_decimal,
}
})
} else if (this.type === 'emoticon') {
const data = this.emoticonList.find(({path}) => path === this.emoticonPath)
if (data) {
return data.list;
}
}
return [];
},
emoticonList() {
if ($A.isArray(window.emoticonData)) {
let baseUrl = $A.apiUrl("../images/emoticon")
return window.emoticonData.map(data => {
data.src = `${baseUrl}/${data.path}/${data.icon}`
data.list = data.list.map(item => {
item.type = `emoticon`
item.asset = `images/emoticon/${data.path}/${item.path}`
item.src = `${baseUrl}/${data.path}/${item.path}`
return item
})
return data;
});
}
return [];
}
},
methods: {
onEmoticon(path) {
this.type = 'emoticon';
this.emoticonPath = path;
},
onSelect(item) {
this.$emit('on-select', item)
}
}
}
</script>

View File

@ -4,26 +4,39 @@
<div class="chat-input-toolbar">
<slot name="toolbarBefore"/>
<ETooltip placement="top" :content="$L('表情')"><i class="taskfont" @click="onToolbar('emoji')">&#xe7ad;</i></ETooltip>
<ETooltip placement="top" :content="$L('选择会员')"><i class="taskfont" @click="onToolbar('user')">&#xe78f;</i></ETooltip>
<ETooltip placement="top" :content="$L('选择任务')"><i class="taskfont" @click="onToolbar('task')">&#xe7d6;</i></ETooltip>
<EPopover
v-model="showEmoji"
:visibleArrow="false"
popperClass="chat-input-emoji-popover">
<ETooltip slot="reference" :disabled="showEmoji" placement="top" :content="$L('表情')">
<i class="taskfont" @click="onToolbar('emoji')">&#xe7ad;</i>
</ETooltip>
<ChatEmoji @on-select="onSelectEmoji"/>
</EPopover>
<EDropdown
trigger="hover"
placement="top"
@command="onToolbar">
<i class="taskfont">&#xe790;</i>
<EDropdownMenu slot="dropdown" class="chat-input-dropdown-menu">
<EDropdownItem command="image">
<i class="taskfont">&#xe64a;</i>
{{$L('图片')}}
</EDropdownItem>
<EDropdownItem command="file">
<i class="taskfont">&#xe786;</i>
{{$L('文件')}}
</EDropdownItem>
</EDropdownMenu>
</EDropdown>
<ETooltip placement="top" :content="$L('选择会员')">
<i class="taskfont" @click="onToolbar('user')">&#xe78f;</i>
</ETooltip>
<ETooltip placement="top" :content="$L('选择任务')">
<i class="taskfont" @click="onToolbar('task')">&#xe7d6;</i>
</ETooltip>
<EPopover
v-model="showMore"
:visibleArrow="false"
popperClass="chat-input-more-popover">
<ETooltip slot="reference" :disabled="showMore" placement="top" :content="$L('展开')">
<i class="taskfont">&#xe790;</i>
</ETooltip>
<div class="chat-input-popover-item" @click="onToolbar('image')">
<i class="taskfont">&#xe64a;</i>
{{$L('图片')}}
</div>
<div class="chat-input-popover-item" @click="onToolbar('file')">
<i class="taskfont">&#xe786;</i>
{{$L('文件')}}
</div>
</EPopover>
<div class="toolbar-spacing"></div>
@ -40,9 +53,11 @@ import {mapGetters, mapState} from "vuex";
import Quill from 'quill';
import "quill-mention";
import ChatEmoji from "./emoji";
export default {
name: 'ChatInput',
components: {ChatEmoji},
props: {
dialogId: {
type: Number,
@ -94,6 +109,9 @@ export default {
userList: null,
taskList: null,
showMore: false,
showEmoji: false,
};
},
mounted() {
@ -266,7 +284,22 @@ export default {
},
send() {
this.$emit('on-send', this.quill)
this.$emit('on-send')
},
onSelectEmoji(item) {
if (!this.quill) {
return;
}
if (item.type === 'emoji') {
let element = document.createElement('span');
element.innerHTML = item.html;
this.quill.insertText(this.quill.getSelection(true).index, element.innerHTML);
element = null;
} else if (item.type === 'emoticon') {
this.$emit('on-send', `<img class="emoticon" data-asset="${item.asset}" data-name="${item.name}" src="${item.src}"/>`)
}
this.showEmoji = false;
},
onToolbar(action) {
@ -286,6 +319,10 @@ export default {
}
},
onMoreVisibleChange(v) {
this.showMore = v;
},
openMenu(char) {
if (!this.quill) {
return;
@ -302,6 +339,26 @@ export default {
}
},
getProjectId() {
let object = null;
if (this.dialogId > 0) {
object = this.cacheProjects.find(({dialog_id}) => dialog_id == this.dialogId);
if (object) {
return object.id;
}
object = this.cacheTasks.find(({dialog_id}) => dialog_id == this.dialogId);
if (object) {
return object.project_id;
}
} else if (this.taskId > 0) {
object = this.cacheTasks.find(({id}) => id == this.taskId);
if (object) {
return object.project_id;
}
}
return 0;
},
getSource(mentionChar) {
return new Promise(resolve => {
switch (mentionChar) {
@ -448,26 +505,6 @@ export default {
}
})
},
getProjectId() {
let object = null;
if (this.dialogId > 0) {
object = this.cacheProjects.find(({dialog_id}) => dialog_id == this.dialogId);
if (object) {
return object.id;
}
object = this.cacheTasks.find(({dialog_id}) => dialog_id == this.dialogId);
if (object) {
return object.project_id;
}
} else if (this.taskId > 0) {
object = this.cacheTasks.find(({id}) => id == this.taskId);
if (object) {
return object.project_id;
}
}
return 0;
}
}
}
</script>

View File

@ -225,10 +225,21 @@ export default {
},
viewText({target}) {
if (target.nodeName === "IMG") {
this.viewPicture(target.currentSrc);
} else if (target.classList.contains('mention') && target.classList.contains('task')) {
this.$store.dispatch("openTask", $A.runNum(target.getAttribute("data-id")));
switch (target.nodeName) {
case "IMG":
if (target.classList.contains('browse')) {
this.viewPicture(target.currentSrc);
} else {
this.$store.state.previewImageIndex = 0;
this.$store.state.previewImageList = [target.currentSrc];
}
break;
case "SPAN":
if (target.classList.contains('mention') && target.classList.contains('task')) {
this.$store.dispatch("openTask", $A.runNum(target.getAttribute("data-id")));
}
break;
}
},
@ -264,7 +275,7 @@ export default {
if (item.type === 'file') {
return ['jpg', 'jpeg', 'gif', 'png'].includes(item.msg.ext);
} else if (item.type === 'text') {
return item.msg.text.match(/<img src="(.*?)"\/>/);
return item.msg.text.match(/<img\s+class="browse"[^>]*?>/);
}
}
return false;
@ -277,9 +288,10 @@ export default {
if (type === 'file') {
list.push(msg.path)
} else if (type === 'text') {
const array = msg.text.match(/<img src="(.*?)"\/>/g);
const baseUrl = $A.apiUrl('../');
const array = msg.text.match(/<img\s+class="browse"[^>]*?src="(.*?)"[^>]*?>/g);
array.some(res => {
list.push(res.match(/<img src="(.*?)"\/>/)[1].replace(/\{\{RemoteURL\}\}/g, $A.apiUrl('../')))
list.push(res.match(/<img\s+class="browse"[^>]*?src="(.*?)"[^>]*?>/)[1].replace(/\{\{RemoteURL\}\}/g, baseUrl))
})
}
})

View File

@ -317,14 +317,18 @@ export default {
methods: {
sendMsg(text) {
let msgText;
if (typeof text === "string" && text) {
this.msgText = text;
this.$refs.input.focus();
msgText = text;
} else {
msgText = this.msgText;
this.msgText = '';
}
if (this.msgText == '') {
if (msgText == '' && this.isDesktop) {
this.$refs.input.focus();
return;
}
this.msgText = this.msgText.replace(/<\/span> <\/p>$/, "</span></p>")
msgText = msgText.replace(/<\/span> <\/p>$/, "</span></p>")
//
let tempId = $A.randomString(16);
this.tempMsgs.push({
@ -333,7 +337,7 @@ export default {
type: 'text',
userid: this.userId,
msg: {
text: this.msgText,
text: msgText,
},
});
if (!this.isDesktop) {
@ -346,7 +350,7 @@ export default {
url: 'dialog/msg/sendtext',
data: {
dialog_id: this.dialogId,
text: this.msgText,
text: msgText,
},
method: 'post'
}).then(({data}) => {
@ -356,8 +360,6 @@ export default {
$A.modalError(msg);
this.tempMsgs = this.tempMsgs.filter(({id}) => id != tempId)
});
//
this.msgText = '';
},
sendFileMsg(files) {

View File

@ -404,10 +404,7 @@ export default {
if ($A.isJson(data)) {
switch (data.type) {
case 'text':
let text = data.msg.text;
text = text.replace(/<img src=".*?"\/>/g, `[${this.$L('图片')}]`)
text = text.replace(/<[^>]+>/g,"")
return text
return $A.getMsgTextPreview(data.msg.text)
case 'file':
if (data.msg.type == 'img') {
return `[${this.$L('图片')}]`

View File

@ -30,6 +30,7 @@
float: left;
max-width: 100%;
min-width: calc(100% - 175px);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
.ql-editor {
padding: 4px 7px;
@ -203,9 +204,11 @@
background-color: #cccccc;
}
> i {
display: inline-block;
cursor: pointer;
padding: 0 5px;
font-size: 20px;
line-height: 28px;
&.disabled {
opacity: 0.5;
}
@ -213,22 +216,118 @@
margin-right: -5px;
}
}
.el-dropdown {
.el-tooltip.taskfont {
display: inline-block;
cursor: pointer;
padding: 0 5px;
> i {
cursor: pointer;
font-size: 20px;
}
font-size: 20px;
line-height: 28px;
}
}
}
.chat-input-dropdown-menu {
> li {
.chat-input-emoji-popover {
padding: 0;
overflow: hidden;
}
.chat-input-more-popover {
min-width: 100px;
padding: 8px;
.chat-input-popover-item {
display: flex;
align-items: center;
font-size: 14px;
cursor: pointer;
line-height: 36px;
padding: 0 8px;
border-radius: 4px;
&:hover {
background-color: #ecf5ff;
}
> i {
font-size: 20px;
margin-right: 8px;
}
}
}
.chat-emoji-wrapper {
display: flex;
flex-direction: column;
.chat-emoji-box {
width: 360px;
height: 280px;
padding: 8px;
overflow-x: hidden;
word-break: break-all;
box-sizing: content-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
> li {
width: 40px;
height: 40px;
line-height: 40px;
font-size: 22px;
text-align: center;
display: inline-block;
cursor: pointer;
user-select: none;
transition: transform 0.3s;
> img {
max-width: 100%;
max-height: 100%;
}
&:hover {
transform: scale(1.4);
}
}
&.emoticon {
> li {
width: 72px;
height: 72px;
padding: 8px;
}
}
}
.chat-emoji-menu {
width: 376px;
height: 40px;
line-height: 40px;
background-color: #f2f4f7;
display: flex;
align-items: center;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
> li {
list-style: none;
cursor: pointer;
display: flex;
align-items: center;
height: 100%;
&.active {
background-color: #fff;
}
> span {
padding: 0 13px;
font-size: 22px;
}
> img {
width: 24px;
height: 24px;
padding: 0 12px;
box-sizing: content-box;
}
}
}
}

View File

@ -40,6 +40,7 @@
opacity: .2;
z-index: 1;
}
.dialog-title {
padding-right: 52px;
}
@ -48,6 +49,7 @@
.dialog-avatar {
flex-shrink: 0;
margin-right: 12px;
.user-avatar,
.icon-avatar {
width: 42px;
@ -56,6 +58,7 @@
flex-grow: 0;
flex-shrink: 0;
}
.icon-avatar {
display: flex;
align-items: center;
@ -64,9 +67,11 @@
font-size: 26px;
background-color: #61B2F9;
color: #ffffff;
&.project {
background-color: #6E99EB;
}
&.task {
background-color: #9B96DF;
font-size: 24px;
@ -226,7 +231,6 @@
align-items: flex-start;
.content-text {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
color: #333333;
> pre {
@ -237,19 +241,30 @@
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-word;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
img {
cursor: pointer;
max-width: 220px;
max-height: 220px;
vertical-align: bottom;
&.emoticon {
max-width: 150px;
max-height: 150px;
}
}
.mention {
color: $flow-status-end-color;
background-color: transparent;
user-select: auto;
margin-right: 0;
> span {
margin: 0;
}
&.task {
cursor: pointer;
}
@ -553,6 +568,7 @@
width: 100%;
display: flex;
align-items: center;
.chat-input-wrapper {
flex: 1;
width: 0;

View File

@ -178,6 +178,8 @@
line-height: 24px;
display: flex;
align-items: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
.common-avatar,
.last-self {
flex-shrink: 0;

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Some files were not shown because too many files have changed in this diff Show More