mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-25 19:52:48 +00:00
parent
16827a37ca
commit
99b9414a4d
|
|
@ -16,8 +16,8 @@
|
|||
"react-dnd": "^9.5.1",
|
||||
"react-dnd-html5-backend": "^9.5.1",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-image-lightbox": "^5.1.1",
|
||||
"react-lazy-load-image-component": "^1.3.2",
|
||||
"react-photoswipe": "^1.3.0",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router": "^5.1.2",
|
||||
"react-router-dom": "^5.1.2",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { navitateTo, changeContextMenu, navitateUp } from "../../actions/index";
|
||||
import ObjectIcon from "./ObjectIcon";
|
||||
import ContextMenu from "./ContextMenu";
|
||||
|
|
@ -138,6 +137,7 @@ const mapDispatchToProps = dispatch => {
|
|||
};
|
||||
|
||||
class ExplorerCompoment extends Component {
|
||||
|
||||
contextMenu = e => {
|
||||
e.preventDefault();
|
||||
if (this.props.keywords === null && !pathHelper.isSharePage(this.props.location.pathname)) {
|
||||
|
|
@ -151,6 +151,7 @@ class ExplorerCompoment extends Component {
|
|||
const { classes } = this.props;
|
||||
|
||||
return (
|
||||
|
||||
<div
|
||||
onContextMenu={this.contextMenu}
|
||||
className={classNames(
|
||||
|
|
@ -229,6 +230,7 @@ class ExplorerCompoment extends Component {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{this.props.viewMethod !== "list" &&
|
||||
(this.props.dirList.length !== 0 ||
|
||||
this.props.fileList.length !== 0) &&
|
||||
|
|
@ -300,7 +302,7 @@ class ExplorerCompoment extends Component {
|
|||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{this.props.viewMethod === "list" &&
|
||||
(this.props.dirList.length !== 0 ||
|
||||
this.props.fileList.length !== 0) &&
|
||||
|
|
@ -328,6 +330,7 @@ class ExplorerCompoment extends Component {
|
|||
</Table>
|
||||
)}
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,130 +1,124 @@
|
|||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux'
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { connect } from "react-redux";
|
||||
import { baseURL } from "../../middleware/Api";
|
||||
import { showImgPreivew } from "../../actions/index";
|
||||
import { imgPreviewSuffix } from "../../config";
|
||||
import { withStyles } from "@material-ui/core";
|
||||
import Lightbox from "react-image-lightbox";
|
||||
import "react-image-lightbox/style.css";
|
||||
|
||||
import {
|
||||
showImgPreivew,
|
||||
}from "../../actions/index"
|
||||
import {imgPreviewSuffix} from "../../config"
|
||||
import PhotoSwipe from'react-photoswipe';
|
||||
import { withStyles } from '@material-ui/core';
|
||||
import('react-photoswipe/lib/photoswipe.css')
|
||||
|
||||
const styles = theme => ({
|
||||
})
|
||||
const styles = theme => ({});
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
first:state.explorer.imgPreview.first,
|
||||
other:state.explorer.imgPreview.other,
|
||||
}
|
||||
}
|
||||
first: state.explorer.imgPreview.first,
|
||||
other: state.explorer.imgPreview.other
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
showImgPreivew:(first)=>{
|
||||
dispatch(showImgPreivew(first))
|
||||
showImgPreivew: first => {
|
||||
dispatch(showImgPreivew(first));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ImgPreviewCompoment extends Component {
|
||||
|
||||
state = {
|
||||
first:[],
|
||||
items:[],
|
||||
open:false,
|
||||
loaded:false,
|
||||
}
|
||||
|
||||
options={
|
||||
history: false,
|
||||
focus: false,
|
||||
showAnimationDuration: 5,
|
||||
hideAnimationDuration: 0,
|
||||
bgOpacity: 0.8,
|
||||
closeOnScroll: 0,
|
||||
items: [],
|
||||
photoIndex: 0,
|
||||
isOpen: false
|
||||
};
|
||||
|
||||
componentWillReceiveProps = (nextProps)=>{
|
||||
componentWillReceiveProps = nextProps => {
|
||||
let items = [];
|
||||
if(nextProps.first!==null){
|
||||
if(!this.state.loaded){
|
||||
this.setState({
|
||||
loaded:true,
|
||||
})
|
||||
}
|
||||
if (nextProps.first !== null) {
|
||||
var firstOne;
|
||||
// eslint-disable-next-line
|
||||
nextProps.other.map((value)=>{
|
||||
let fileType =value.name.split(".").pop().toLowerCase();
|
||||
|
||||
if(imgPreviewSuffix.indexOf(fileType)!==-1){
|
||||
nextProps.other.map(value => {
|
||||
let fileType = value.name
|
||||
.split(".")
|
||||
.pop()
|
||||
.toLowerCase();
|
||||
|
||||
if (imgPreviewSuffix.indexOf(fileType) !== -1) {
|
||||
let newImg = {
|
||||
h:0,
|
||||
w:0,
|
||||
title:value.name,
|
||||
src:window.apiURL.preview+"?action=preview&path="+encodeURIComponent(value.path==="/"?value.path+value.name:value.path+"/"+value.name),
|
||||
title: value.name,
|
||||
src:
|
||||
baseURL +
|
||||
"/file" +
|
||||
(value.path === "/"
|
||||
? value.path + value.name
|
||||
: value.path + "/" + value.name)
|
||||
};
|
||||
if((value.path===nextProps.first.path)&&(value.name===nextProps.first.name)){
|
||||
if (
|
||||
value.path === nextProps.first.path &&
|
||||
value.name === nextProps.first.name
|
||||
) {
|
||||
firstOne = newImg;
|
||||
}else{
|
||||
} else {
|
||||
items.push(newImg);
|
||||
}
|
||||
}
|
||||
});
|
||||
items.unshift(firstOne);
|
||||
this.setState({
|
||||
items:items,
|
||||
open:true,
|
||||
items: items,
|
||||
isOpen: true
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleClose=()=>{
|
||||
handleClose = () => {
|
||||
this.props.showImgPreivew(null);
|
||||
this.setState({
|
||||
loaded:true,
|
||||
open:false,
|
||||
isOpen: false
|
||||
});
|
||||
}
|
||||
|
||||
setSize = (ps,index,item)=>{
|
||||
if (item.h < 1 || item.w < 1) {
|
||||
let img = new Image()
|
||||
img.onload = () => {
|
||||
item.w = img.width
|
||||
item.h = img.height
|
||||
ps.invalidateCurrItems()
|
||||
ps.updateSize(true)
|
||||
}
|
||||
img.src = item.src
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
if(this.state.loaded){
|
||||
return (
|
||||
<div>
|
||||
<PhotoSwipe isOpen={this.state.open} items={this.state.items} options={this.options} onClose={this.handleClose} imageLoadComplete={this.setSize}/>
|
||||
</div>
|
||||
);
|
||||
}else{
|
||||
return (<div></div>);
|
||||
}
|
||||
|
||||
const { photoIndex, isOpen,items } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isOpen && (<Lightbox
|
||||
mainSrc={items[photoIndex].src}
|
||||
nextSrc={items[(photoIndex + 1) % items.length].src}
|
||||
prevSrc={items[(photoIndex + items.length - 1) % items.length].src}
|
||||
onCloseRequest={() => this.handleClose()}
|
||||
imageLoadErrorMessage = "无法加载此图像"
|
||||
imageCrossOrigin = "use-credentials"
|
||||
imageTitle = {items[photoIndex].title}
|
||||
onMovePrevRequest={() =>
|
||||
this.setState({
|
||||
photoIndex: (photoIndex + items.length - 1) % items.length,
|
||||
})
|
||||
}
|
||||
reactModalStyle={{
|
||||
overlay:{
|
||||
zIndex:10000
|
||||
},
|
||||
}}
|
||||
onMoveNextRequest={() =>
|
||||
this.setState({
|
||||
photoIndex: (photoIndex + 1) % items.length,
|
||||
})
|
||||
}
|
||||
/>)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImgPreviewCompoment.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
classes: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
|
||||
const ImgPreivew = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(withStyles(styles)(ImgPreviewCompoment))
|
||||
)(withStyles(styles)(ImgPreviewCompoment));
|
||||
|
||||
export default ImgPreivew
|
||||
export default ImgPreivew;
|
||||
|
|
|
|||
|
|
@ -174,9 +174,9 @@ class ModalsCompoment extends Component {
|
|||
// eslint-disable-next-line
|
||||
this.props.selected.map((value)=>{
|
||||
if(value.type==="dir"){
|
||||
dirs.push(value.path === "/" ? value.path+value.name:value.path+"/"+value.name);
|
||||
dirs.push(value.id);
|
||||
}else{
|
||||
items.push(value.path === "/" ? value.path+value.name:value.path+"/"+value.name);
|
||||
items.push(value.id);
|
||||
}
|
||||
});
|
||||
API.delete('/object', { data: {
|
||||
|
|
@ -229,9 +229,9 @@ class ModalsCompoment extends Component {
|
|||
// eslint-disable-next-line
|
||||
this.props.selected.map((value)=>{
|
||||
if(value.type==="dir"){
|
||||
dirs.push(value.name);
|
||||
dirs.push(value.id);
|
||||
}else{
|
||||
items.push(value.name);
|
||||
items.push(value.id);
|
||||
}
|
||||
});
|
||||
API.patch('/object', {
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ export default function ObjectIcon(props) {
|
|||
const dropResult = monitor.getDropResult();
|
||||
if (item && dropResult) {
|
||||
if (dropResult.folder){
|
||||
if (item.object.id != dropResult.folder.id){
|
||||
if (item.object.id != dropResult.folder.id || item.object.type != dropResult.folder.type){
|
||||
DragAndDrop(item.object,dropResult.folder);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,9 +76,9 @@ export default function CopyDialog(props) {
|
|||
// eslint-disable-next-line
|
||||
|
||||
if (props.selected[0].type === "dir") {
|
||||
dirs.push(props.selected[0].name);
|
||||
dirs.push(props.selected[0].id);
|
||||
} else {
|
||||
items.push(props.selected[0].name);
|
||||
items.push(props.selected[0].id);
|
||||
}
|
||||
|
||||
API.post("/object/copy", {
|
||||
|
|
|
|||
|
|
@ -176,6 +176,9 @@ const styles = theme => ({
|
|||
drawerPaper:{
|
||||
width:drawerWidthMobile,
|
||||
},
|
||||
upDrawer:{
|
||||
marginBottom: 90,
|
||||
},
|
||||
drawerOpen: {
|
||||
width: drawerWidth,
|
||||
transition: theme.transitions.create('width', {
|
||||
|
|
@ -357,28 +360,13 @@ class NavbarCompoment extends Component {
|
|||
const { classes } = this.props;
|
||||
|
||||
const drawer = (
|
||||
<div id="container">
|
||||
<div
|
||||
id="container"
|
||||
className={classes.upDrawer}
|
||||
>
|
||||
{pathHelper.isMobile()&&
|
||||
<UserInfo/>
|
||||
}
|
||||
{pathHelper.isHomePage(this.props.location.pathname)&&
|
||||
<div className={classes.addButton}>
|
||||
<Badge badgeContent={this.state.queued} classes={{ badge: classes.badgeFix }} invisible={this.state.queued === 0} color="secondary">
|
||||
<Button
|
||||
disabled={this.props.keywords!==null}
|
||||
variant="outlined"
|
||||
size="large"
|
||||
color="primary"
|
||||
onClick = {this.clickUpload}
|
||||
className={classes.fabButton}
|
||||
>
|
||||
<AddIcon className={classes.extendedIcon} /> 新建项目
|
||||
|
||||
|
||||
</Button>
|
||||
</Badge>
|
||||
</div>
|
||||
}
|
||||
{(!pathHelper.isHomePage(this.props.location.pathname)&&Auth.Check())&&
|
||||
<div>
|
||||
<ListItem button key="我的文件" onClick={()=>window.location.href="/"}>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import React, { Component } from 'react'
|
|||
import PropTypes from 'prop-types';
|
||||
import StorageIcon from '@material-ui/icons/Storage'
|
||||
import { connect } from 'react-redux'
|
||||
import axios from 'axios'
|
||||
import API from "../middleware/Api"
|
||||
import {sizeToString} from "../untils/index"
|
||||
import {
|
||||
toggleSnackbar,
|
||||
}from "../actions/index"
|
||||
|
|
@ -26,7 +27,7 @@ const mapDispatchToProps = dispatch => {
|
|||
const styles = theme => ({
|
||||
iconFix:{
|
||||
marginLeft: "32px",
|
||||
marginRight: "32px",
|
||||
marginRight: "17px",
|
||||
color: theme.palette.text.secondary,
|
||||
marginTop: "2px",
|
||||
},
|
||||
|
|
@ -41,7 +42,7 @@ const styles = theme => ({
|
|||
},
|
||||
detail:{
|
||||
width: "100%",
|
||||
marginRight: "20px",
|
||||
marginRight: "35px",
|
||||
},
|
||||
info:{
|
||||
width:"131px",
|
||||
|
|
@ -52,7 +53,7 @@ const styles = theme => ({
|
|||
},
|
||||
stickFooter:{
|
||||
bottom: "0px",
|
||||
position: "absolute",
|
||||
position: "fixed",
|
||||
backgroundColor:theme.palette.background.paper,
|
||||
},
|
||||
})
|
||||
|
|
@ -83,18 +84,18 @@ class StorageBarCompoment extends Component {
|
|||
|
||||
updateStatus = ()=>{
|
||||
let percent = 0;
|
||||
axios.get('/Member/Memory')
|
||||
API.get('/user/storage')
|
||||
.then( (response)=> {
|
||||
if(response.data.rate>=100){
|
||||
if((response.data.used / response.data.total)>=100){
|
||||
percent = 100;
|
||||
this.props.toggleSnackbar("top","right","您的已用容量已超过容量配额,请尽快删除多余文件或购买容量","warning");
|
||||
}else{
|
||||
percent = response.data.rate;
|
||||
percent = (response.data.used / response.data.total);
|
||||
}
|
||||
this.setState({
|
||||
percent:percent,
|
||||
used:response.data.used,
|
||||
total:response.data.total,
|
||||
used:sizeToString(response.data.used),
|
||||
total:sizeToString(response.data.total),
|
||||
});
|
||||
})
|
||||
.catch((error) =>{
|
||||
|
|
|
|||
51
yarn.lock
51
yarn.lock
|
|
@ -2579,7 +2579,7 @@ class-utils@^0.3.5:
|
|||
isobject "^3.0.0"
|
||||
static-extend "^0.1.1"
|
||||
|
||||
classnames@^2.2.3, classnames@^2.2.6:
|
||||
classnames@^2.2.6:
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
||||
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
||||
|
|
@ -4000,6 +4000,11 @@ execa@^1.0.0:
|
|||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
exenv@^1.2.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
|
||||
integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=
|
||||
|
||||
exit@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
|
||||
|
|
@ -6295,11 +6300,6 @@ lodash.memoize@^4.1.2:
|
|||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
|
||||
|
||||
lodash.pick@^4.2.1:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
|
||||
integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=
|
||||
|
||||
lodash.sortby@^4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||
|
|
@ -7408,11 +7408,6 @@ performance-now@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
photoswipe@^4.1.0:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/photoswipe/-/photoswipe-4.1.3.tgz#59f49494eeb9ddab5888d03392926a19bc197550"
|
||||
integrity sha512-89Z43IRUyw7ycTolo+AaiDn3W1EEIfox54hERmm9bI12IB9cvRfHSHez3XhAyU8XW2EAFrC+2sKMhh7SJwn0bA==
|
||||
|
||||
picomatch@^2.0.5:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
|
||||
|
|
@ -8504,6 +8499,14 @@ react-error-overlay@^6.0.3:
|
|||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.3.tgz#c378c4b0a21e88b2e159a3e62b2f531fd63bf60d"
|
||||
integrity sha512-bOUvMWFQVk5oz8Ded9Xb7WVdEi3QGLC8tH7HmYP0Fdp4Bn3qw0tRFmr5TW6mvahzvmrK4a6bqWGfCevBflP+Xw==
|
||||
|
||||
react-image-lightbox@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-image-lightbox/-/react-image-lightbox-5.1.1.tgz#872d1a4336b5a6410ea7909b767cf59014081004"
|
||||
integrity sha512-GprldD8AqpRb2hsOdns3sI7Xeo9hJlcybDxuli4RB+ml1J/GaFaUuRkT/7IrTLv2+4vkR74ahz2LD0HOUHI7wA==
|
||||
dependencies:
|
||||
prop-types "^15.6.2"
|
||||
react-modal "^3.8.1"
|
||||
|
||||
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.6, react-is@^16.9.0:
|
||||
version "16.12.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
|
||||
|
|
@ -8522,15 +8525,20 @@ react-lazy-load-image-component@^1.3.2:
|
|||
lodash.debounce "^4.0.8"
|
||||
lodash.throttle "^4.1.1"
|
||||
|
||||
react-photoswipe@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-photoswipe/-/react-photoswipe-1.3.0.tgz#016dd978450a8406776db97511eaf96f2ffb9cfb"
|
||||
integrity sha512-1ok6vXFAj/rd60KIzF0YwCdq1Tcl+8yKqWJHbPo43lJBuwUi+LBosmBdJmswpiOzMn2496ekU0k/r6aHWQk7PQ==
|
||||
react-lifecycles-compat@^3.0.0:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-modal@^3.8.1:
|
||||
version "3.11.1"
|
||||
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.11.1.tgz#2a0d6877c9e98f123939ea92d2bb4ad7fa5a17f9"
|
||||
integrity sha512-8uN744Yq0X2lbfSLxsEEc2UV3RjSRb4yDVxRQ1aGzPo86QjNOwhQSukDb8U8kR+636TRTvfMren10fgOjAy9eA==
|
||||
dependencies:
|
||||
classnames "^2.2.3"
|
||||
lodash.pick "^4.2.1"
|
||||
photoswipe "^4.1.0"
|
||||
exenv "^1.2.0"
|
||||
prop-types "^15.5.10"
|
||||
react-lifecycles-compat "^3.0.0"
|
||||
warning "^4.0.3"
|
||||
|
||||
react-redux@^7.1.3:
|
||||
version "7.1.3"
|
||||
|
|
@ -10301,6 +10309,13 @@ walker@^1.0.7, walker@~1.0.5:
|
|||
dependencies:
|
||||
makeerror "1.0.x"
|
||||
|
||||
warning@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
|
||||
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
watchpack@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
|
||||
|
|
|
|||
Loading…
Reference in New Issue