优化输入框区域以及文章图片展示
This commit is contained in:
parent
aae91ddd91
commit
71d448e72b
70
package-lock.json
generated
70
package-lock.json
generated
@ -1,34 +1,40 @@
|
||||
{
|
||||
"name": "ykt-wxapp",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ykt-wxapp",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"dayjs": "^1.11.10",
|
||||
"tim-upload-plugin": "^1.4.2",
|
||||
"tim-wx-sdk": "^2.27.6"
|
||||
},
|
||||
"devDependencies": {}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.19",
|
||||
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz",
|
||||
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
|
||||
},
|
||||
"node_modules/tim-upload-plugin": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/tim-upload-plugin/-/tim-upload-plugin-1.4.3.tgz",
|
||||
"integrity": "sha512-3ZmbA36dr3eG9YGDon9MLBUtbNawYWkL+TBa+VS0Uviguc7PlVSOIVRG2C4irXX16slDT2Kj+HAZapp+Xqp2xg=="
|
||||
},
|
||||
"node_modules/tim-wx-sdk": {
|
||||
"version": "2.27.6",
|
||||
"resolved": "https://registry.npmmirror.com/tim-wx-sdk/-/tim-wx-sdk-2.27.6.tgz",
|
||||
"integrity": "sha512-zB+eRdmigdhEDeqrXC0bLJonUQZzS5uKNPLFtrje503WAnmuxVQjq/n4Zle4FYHG4FiKHKhsrVd0aCYXABlFEg=="
|
||||
}
|
||||
}
|
||||
"name": "医客通患者端",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "医客通患者端",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"dayjs": "^1.11.10",
|
||||
"mp-html": "^2.5.2",
|
||||
"tim-upload-plugin": "^1.4.2",
|
||||
"tim-wx-sdk": "^2.27.6"
|
||||
},
|
||||
"devDependencies": {}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.19",
|
||||
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz",
|
||||
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
|
||||
},
|
||||
"node_modules/mp-html": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmmirror.com/mp-html/-/mp-html-2.5.2.tgz",
|
||||
"integrity": "sha512-45e8c32Qgux4YU4iC3qCSFsOh3y+RwPwZ+iz/vvLkDgSGWk+1zsL4WUzWWQc9w3AsAfkaD/QR0oIufIDngBmXA=="
|
||||
},
|
||||
"node_modules/tim-upload-plugin": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/tim-upload-plugin/-/tim-upload-plugin-1.4.3.tgz",
|
||||
"integrity": "sha512-3ZmbA36dr3eG9YGDon9MLBUtbNawYWkL+TBa+VS0Uviguc7PlVSOIVRG2C4irXX16slDT2Kj+HAZapp+Xqp2xg=="
|
||||
},
|
||||
"node_modules/tim-wx-sdk": {
|
||||
"version": "2.27.6",
|
||||
"resolved": "https://registry.npmmirror.com/tim-wx-sdk/-/tim-wx-sdk-2.27.6.tgz",
|
||||
"integrity": "sha512-zB+eRdmigdhEDeqrXC0bLJonUQZzS5uKNPLFtrje503WAnmuxVQjq/n4Zle4FYHG4FiKHKhsrVd0aCYXABlFEg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
package.json
15
package.json
@ -11,6 +11,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"dayjs": "^1.11.10",
|
||||
"mp-html": "^2.5.2",
|
||||
"tim-upload-plugin": "^1.4.2",
|
||||
"tim-wx-sdk": "^2.27.6"
|
||||
},
|
||||
@ -27,14 +28,14 @@
|
||||
"env": {
|
||||
"UNI_PLATFORM": "mp-weixin"
|
||||
}
|
||||
},
|
||||
"pro": {
|
||||
"title": "线上",
|
||||
"env": {
|
||||
"UNI_PLATFORM": "mp-weixin"
|
||||
}
|
||||
},
|
||||
"pro": {
|
||||
"title": "线上",
|
||||
"env": {
|
||||
"UNI_PLATFORM": "mp-weixin"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,12 @@
|
||||
</view>
|
||||
<view class="article-body">
|
||||
<view class="rich-text-wrapper">
|
||||
<rich-text :nodes="articleData.content"></rich-text>
|
||||
<mp-html
|
||||
:content="articleData.content"
|
||||
:tag-style="richTextTagStyle"
|
||||
:preview-img="true"
|
||||
:lazy-load="true"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@ -35,6 +40,7 @@ import { toast } from "@/utils/widget.js";
|
||||
import { ref } from "vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import useAccountStore from "@/store/account.js";
|
||||
import mpHtml from "mp-html/dist/uni-app/components/mp-html/mp-html";
|
||||
const { account } = storeToRefs(useAccountStore());
|
||||
const { login } = useAccountStore()
|
||||
const loading = ref(true);
|
||||
@ -44,6 +50,9 @@ const articleData = ref({
|
||||
content: "",
|
||||
date: "",
|
||||
});
|
||||
const richTextTagStyle = {
|
||||
img: "max-width:100%;height:auto;display:block;margin:10px 0;",
|
||||
};
|
||||
|
||||
let articleId = "";
|
||||
const corpId = ref("");
|
||||
@ -66,25 +75,18 @@ const markArticleRead = async (sendId) => {
|
||||
const processRichTextContent = (html) => {
|
||||
if (!html) return "";
|
||||
|
||||
// 给所有 img 标签添加样式
|
||||
let processedHtml = html.replace(
|
||||
/<img/gi,
|
||||
'<img style="max-width:100%;height:auto;display:block;margin:10px 0;"'
|
||||
);
|
||||
let processedHtml = html.replace(/<img\b([^>]*)>/gi, (tag, attrs) => {
|
||||
const cleanedAttrs = attrs
|
||||
.replace(/\s+(width|height)\s*=\s*(['"])[\s\S]*?\2/gi, "")
|
||||
.replace(/\s+style\s*=\s*(['"])([\s\S]*?)\1/gi, (match, quote, style) => {
|
||||
const cleanedStyle = style
|
||||
.replace(/(?:^|;)\s*(?:min-|max-)?(?:width|height)\s*:[^;]*/gi, "")
|
||||
.trim();
|
||||
return cleanedStyle ? ` style=${quote}${cleanedStyle}${quote}` : "";
|
||||
});
|
||||
|
||||
// 移除可能存在的固定宽度样式
|
||||
processedHtml = processedHtml.replace(
|
||||
/style="[^"]*width:\s*\d+px[^"]*"/gi,
|
||||
(match) => {
|
||||
return match.replace(/width:\s*\d+px;?/gi, "max-width:100%;");
|
||||
}
|
||||
);
|
||||
|
||||
// 处理表格,添加自适应样式
|
||||
processedHtml = processedHtml.replace(
|
||||
/<table/gi,
|
||||
'<table style="max-width:100%;overflow-x:auto;display:block;"'
|
||||
);
|
||||
return `<img${cleanedAttrs}>`;
|
||||
});
|
||||
|
||||
// 给整体内容添加容器样式
|
||||
processedHtml = `<div style="width:100%;overflow-x:hidden;word-wrap:break-word;word-break:break-all;">${processedHtml}</div>`;
|
||||
@ -275,13 +277,4 @@ onLoad((options) => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rich-text-wrapper ::v-deep rich-text {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.rich-text-wrapper ::v-deep rich-text img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -95,7 +95,12 @@
|
||||
</view>
|
||||
<scroll-view scroll-y class="preview-content">
|
||||
<view class="rich-text-wrapper">
|
||||
<rich-text :nodes="previewArticleData.content"></rich-text>
|
||||
<mp-html
|
||||
:content="previewArticleData.content"
|
||||
:tag-style="richTextTagStyle"
|
||||
:preview-img="true"
|
||||
:lazy-load="true"
|
||||
/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="preview-footer">
|
||||
@ -112,6 +117,7 @@ import { onLoad } from "@dcloudio/uni-app";
|
||||
import api from "@/utils/api.js";
|
||||
import useAccountStore from "@/store/account.js";
|
||||
import EmptyData from "@/components/empty-data.vue";
|
||||
import mpHtml from "mp-html/dist/uni-app/components/mp-html/mp-html";
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
const env = __VITE_ENV__;
|
||||
@ -143,6 +149,9 @@ const previewArticleData = ref({
|
||||
title: "",
|
||||
content: "",
|
||||
});
|
||||
const richTextTagStyle = {
|
||||
img: "max-width:100%;height:auto;display:block;margin:10px 0;",
|
||||
};
|
||||
const previewPopup = ref(null);
|
||||
|
||||
// 获取分类列表
|
||||
@ -250,25 +259,18 @@ const loadMore = () => {
|
||||
const processRichTextContent = (html) => {
|
||||
if (!html) return "";
|
||||
|
||||
// 给所有 img 标签添加样式
|
||||
let processedHtml = html.replace(
|
||||
/<img/gi,
|
||||
'<img style="max-width:100%;height:auto;display:block;margin:10px 0;"'
|
||||
);
|
||||
let processedHtml = html.replace(/<img\b([^>]*)>/gi, (tag, attrs) => {
|
||||
const cleanedAttrs = attrs
|
||||
.replace(/\s+(width|height)\s*=\s*(['"])[\s\S]*?\2/gi, "")
|
||||
.replace(/\s+style\s*=\s*(['"])([\s\S]*?)\1/gi, (match, quote, style) => {
|
||||
const cleanedStyle = style
|
||||
.replace(/(?:^|;)\s*(?:min-|max-)?(?:width|height)\s*:[^;]*/gi, "")
|
||||
.trim();
|
||||
return cleanedStyle ? ` style=${quote}${cleanedStyle}${quote}` : "";
|
||||
});
|
||||
|
||||
// 移除可能存在的固定宽度样式
|
||||
processedHtml = processedHtml.replace(
|
||||
/style="[^"]*width:\s*\d+px[^"]*"/gi,
|
||||
(match) => {
|
||||
return match.replace(/width:\s*\d+px;?/gi, "max-width:100%;");
|
||||
}
|
||||
);
|
||||
|
||||
// 处理表格,添加自适应样式
|
||||
processedHtml = processedHtml.replace(
|
||||
/<table/gi,
|
||||
'<table style="max-width:100%;overflow-x:auto;display:block;"'
|
||||
);
|
||||
return `<img${cleanedAttrs}>`;
|
||||
});
|
||||
|
||||
// 给整体内容添加容器样式
|
||||
processedHtml = `<div style="width:100%;overflow-x:hidden;word-wrap:break-word;word-break:break-all;">${processedHtml}</div>`;
|
||||
@ -567,17 +569,6 @@ onMounted(() => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* rich-text 内部样式 */
|
||||
.rich-text-wrapper ::v-deep rich-text {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.rich-text-wrapper ::v-deep rich-text img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.preview-footer {
|
||||
padding: 20rpx;
|
||||
border-top: 1px solid #eee;
|
||||
|
||||
@ -432,12 +432,31 @@ $primary-color: #0877F1;
|
||||
|
||||
.input-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-end;
|
||||
position: relative;
|
||||
padding: 12rpx 20rpx;
|
||||
padding-bottom: 40rpx;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.input-section.is-input-expanded {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.expand-input-btn {
|
||||
position: absolute;
|
||||
top: 12rpx;
|
||||
left: 20rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
z-index: 1;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.voice-toggle-btn {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
@ -446,6 +465,7 @@ $primary-color: #0877F1;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.voice-toggle-icon {
|
||||
@ -464,6 +484,7 @@ $primary-color: #0877F1;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
@ -483,6 +504,7 @@ $primary-color: #0877F1;
|
||||
transition: background 0.2s;
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.send-btn:active {
|
||||
@ -522,6 +544,49 @@ $primary-color: #0877F1;
|
||||
display: block;
|
||||
line-height: 1.5;
|
||||
height: 80rpx;
|
||||
max-height: 500rpx;
|
||||
}
|
||||
|
||||
.expanded-input-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.expanded-input-header {
|
||||
height: 96rpx;
|
||||
flex-shrink: 0;
|
||||
padding: 24rpx 24rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.collapse-input-btn {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.expanded-text-input {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
padding: 0 32rpx 32rpx;
|
||||
box-sizing: border-box;
|
||||
font-size: 30rpx;
|
||||
line-height: 1.5;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<view class="input-section" :style="{ bottom: props.keyboardHeight + 'px' }">
|
||||
<view class="input-section" :class="{ 'is-input-expanded': isInputExpanded }"
|
||||
:style="{ bottom: props.keyboardHeight + 'px' }">
|
||||
<view class="input-toolbar">
|
||||
<view v-if="showExpandButton" class="expand-input-btn" @click="expandInput">
|
||||
<image src="/static/expand.svg" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view @click="toggleVoiceInput" class="voice-toggle-btn">
|
||||
<image v-if="showVoiceInput" src="/static/jianpan.png" class="voice-toggle-icon" mode="aspectFit"></image>
|
||||
<uni-icons v-else type="mic" size="28" color="#666" />
|
||||
@ -21,6 +25,16 @@
|
||||
<uni-icons type="plusempty" size="28" color="#666" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isInputExpanded" class="expanded-input-overlay" :style="{ bottom: props.keyboardHeight + 'px' }">
|
||||
<view class="expanded-input-header">
|
||||
<view class="collapse-input-btn" @click="collapseInput">
|
||||
<image src="/static/mini.svg" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
<textarea class="expanded-text-input" v-model="inputText" placeholder="我来说两句..."
|
||||
@confirm="sendTextMessage" @focus="handleExpandedInputFocus" @input="handleInput" :focus="expandedTextareaFocus"
|
||||
:auto-height="false" :show-confirm-bar="false" :adjust-position="false" :hold-keyboard="true" />
|
||||
</view>
|
||||
<view class="more-panel" v-if="showMorePanel">
|
||||
<view v-for="btn in morePanelButtons" :key="btn.text" class="more-btn" @click="btn.action">
|
||||
<image :src="btn.icon" class="more-icon" mode="aspectFit"></image>
|
||||
@ -55,7 +69,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import { computed, getCurrentInstance, ref, onMounted, onUnmounted, nextTick, watch } from "vue";
|
||||
import {
|
||||
chooseImage,
|
||||
takePhoto as takePhotoUtil,
|
||||
@ -91,6 +105,12 @@ const showVoiceInput = ref(false);
|
||||
const showMorePanel = ref(false);
|
||||
const isRecording = ref(false);
|
||||
const recordingText = ref("录音中...");
|
||||
const isInputExpanded = ref(false);
|
||||
const isInputOverFourLines = ref(false);
|
||||
const expandedTextareaFocus = ref(false);
|
||||
const singleLineInputHeight = ref(0);
|
||||
const instanceProxy = getCurrentInstance()?.proxy;
|
||||
const showExpandButton = computed(() => !showVoiceInput.value && isInputOverFourLines.value && !isInputExpanded.value);
|
||||
const cloudCustomData = computed(() => {
|
||||
const arr = [
|
||||
props.chatRoomBusiness.businessType,
|
||||
@ -99,6 +119,54 @@ const cloudCustomData = computed(() => {
|
||||
return arr.filter(Boolean).join("|");
|
||||
});
|
||||
|
||||
const updateInputLines = async () => {
|
||||
await nextTick();
|
||||
if (showVoiceInput.value || isInputExpanded.value) return;
|
||||
|
||||
const hasExplicitLineBreak = /[\r\n]/.test(inputText.value);
|
||||
if (hasExplicitLineBreak) {
|
||||
isInputOverFourLines.value = inputText.value.split(/\r\n|\r|\n/).length > 4;
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputText.value.length <= 1 && singleLineInputHeight.value) {
|
||||
isInputOverFourLines.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const query = instanceProxy ? uni.createSelectorQuery().in(instanceProxy) : uni.createSelectorQuery();
|
||||
query.select(".text-input").boundingClientRect();
|
||||
query.exec((res) => {
|
||||
const inputRect = res && res[0];
|
||||
if (!inputRect) return;
|
||||
|
||||
if (!singleLineInputHeight.value) singleLineInputHeight.value = inputRect.height;
|
||||
|
||||
const lineHeight = (45 * uni.getSystemInfoSync().windowWidth) / 750;
|
||||
const fourLineHeight = singleLineInputHeight.value + lineHeight * 3;
|
||||
isInputOverFourLines.value = inputRect.height > fourLineHeight + 1;
|
||||
});
|
||||
};
|
||||
|
||||
const expandInput = () => {
|
||||
isInputFocused.value = false;
|
||||
isInputExpanded.value = true;
|
||||
nextTick(() => {
|
||||
expandedTextareaFocus.value = true;
|
||||
});
|
||||
};
|
||||
|
||||
const collapseInput = () => {
|
||||
expandedTextareaFocus.value = false;
|
||||
isInputExpanded.value = false;
|
||||
nextTick(() => {
|
||||
isInputFocused.value = true;
|
||||
updateInputLines();
|
||||
});
|
||||
};
|
||||
|
||||
watch(inputText, updateInputLines);
|
||||
|
||||
// 录音相关扩展状态(特效 + 取消逻辑)
|
||||
const recordingDuration = ref(0);
|
||||
let recordingTimer = null;
|
||||
@ -354,6 +422,12 @@ function handleInputFocus() {
|
||||
});
|
||||
}
|
||||
|
||||
function handleExpandedInputFocus() {
|
||||
nextTick().then(() => {
|
||||
emit("scrollToBottom");
|
||||
});
|
||||
}
|
||||
|
||||
function handleInputBlur() {
|
||||
isInputFocused.value = false;
|
||||
}
|
||||
@ -377,6 +451,7 @@ defineExpose({
|
||||
onMounted(() => {
|
||||
// 初始化录音管理器
|
||||
initRecorderManager();
|
||||
updateInputLines();
|
||||
|
||||
// 监听关闭功能栏事件
|
||||
uni.$on("closeMorePanel", () => {
|
||||
|
||||
1
static/expand.svg
Normal file
1
static/expand.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1792130980667" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1700" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M459.712 507.568L208 759.28V528H128v368h368v-80H264.56l251.728-251.792-56.576-56.64zM528 128v80h231.44L507.712 459.712l56.576 56.576L816 264.56V496h80V128H528z" fill="#565D64" p-id="1701"></path></svg>
|
||||
|
After Width: | Height: | Size: 535 B |
1
static/mini.svg
Normal file
1
static/mini.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1792131033804" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3515" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M104.704 338.752a64 64 0 0 1 90.496 0L512 655.552l316.8-316.8a64 64 0 0 1 90.496 90.496l-362.048 362.048a64 64 0 0 1-90.496 0L104.704 429.248a64 64 0 0 1 0-90.496z" p-id="3516"></path></svg>
|
||||
|
After Width: | Height: | Size: 524 B |
Loading…
x
Reference in New Issue
Block a user