mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 10:34:17 +00:00
add persistent mode to use
& other changes
This commit is contained in:
parent
878143c515
commit
736f933ce5
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import styles from './like.less'
|
||||
import styles from './index.less'
|
||||
import * as core from 'core'
|
||||
import classnames from 'classnames'
|
||||
|
||||
@ -9,15 +9,22 @@ export default class LikeBtn extends React.Component {
|
||||
count: this.props.count,
|
||||
clicked: false,
|
||||
}
|
||||
handleClick(){
|
||||
if (typeof(this.props.handleClick) !== "undefined") {
|
||||
this.props.handleClick()
|
||||
this.setState({ clicked: true })
|
||||
setTimeout(() => {
|
||||
this.setState({ clicked: false, liked: !this.state.liked })
|
||||
}, 500)
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { id } = this.props
|
||||
const { count, liked, clicked } = this.state
|
||||
|
||||
const { liked, clicked } = this.state
|
||||
return (
|
||||
<div className={styles.btnWrapper}>
|
||||
<button className={classnames(styles.like_button, {[styles.clickanim]: clicked })} >
|
||||
<button onClick={() => { this.handleClick() }} className={classnames(styles.like_button, {[styles.clickanim]: clicked })} >
|
||||
<div className={styles.like_wrapper}>
|
||||
<div
|
||||
className={classnames(
|
||||
@ -39,15 +46,6 @@ export default class LikeBtn extends React.Component {
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<p
|
||||
className={classnames(styles.likeCounter, {
|
||||
[styles.active]: !clicked,
|
||||
[styles.past]: clicked,
|
||||
})}
|
||||
>
|
||||
{count}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -12,38 +12,6 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.btnWrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.likeCounter {
|
||||
font-family: "Poppins", sans-serif;
|
||||
line-height: 70px;
|
||||
margin: 0 0 0 10px;
|
||||
|
||||
opacity: 0;
|
||||
transform: perspective(100px) translateZ(10px);
|
||||
filter: blur(10px);
|
||||
letter-spacing: 0.1em;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
transform: perspective(100px) translateZ(0px);
|
||||
filter: blur(0px);
|
||||
letter-spacing: 0.15em;
|
||||
transition: opacity 1000ms linear, transform 1000ms linear, filter 400ms linear, letter-spacing 1000ms linear;
|
||||
}
|
||||
|
||||
&.past {
|
||||
opacity: 0;
|
||||
transform: perspective(100px) translateZ(-10px);
|
||||
filter: blur(10px);
|
||||
letter-spacing: 0.2em;
|
||||
transition: opacity 1000ms linear, transform 1000ms linear, filter 400ms linear, letter-spacing 1000ms linear;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.like_button {
|
||||
--color-heart: #EA442B;
|
||||
--easing: cubic-bezier(.7, 0, .3, 1);
|
||||
@ -115,10 +83,10 @@
|
||||
}
|
||||
|
||||
.like_wrapper {
|
||||
display: grid;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
z-index: 5;
|
||||
|
||||
>* {
|
||||
margin: auto;
|
||||
@ -127,10 +95,9 @@
|
||||
}
|
||||
|
||||
.heart {
|
||||
width: .5em;
|
||||
height: .5em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
transform-origin: center 80%;
|
||||
|
||||
>path {
|
||||
stroke: var(--color-heart);
|
||||
@ -168,8 +135,9 @@
|
||||
}
|
||||
|
||||
.ripple {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { useLayoutEffect } from 'react'
|
||||
import * as antd from 'antd'
|
||||
import styles from './index.less'
|
||||
import { MediaPlayer } from 'components'
|
||||
@ -9,7 +9,7 @@ import classnames from 'classnames'
|
||||
|
||||
import settings from 'core/libs/settings'
|
||||
import { router } from 'core/libs'
|
||||
import LikeBtn from './components/like'
|
||||
import LikeBtn from './components/like/index.js'
|
||||
import { connect } from 'umi'
|
||||
|
||||
const { Meta } = antd.Card
|
||||
@ -47,7 +47,7 @@ const contextMenuList = [
|
||||
title: "Save screenshot",
|
||||
icon: <Icons.Aperture />,
|
||||
params: {
|
||||
itemProps: {
|
||||
itemProps: {
|
||||
style: { color: "#40a9ff" }
|
||||
},
|
||||
onClick: (e) => {
|
||||
@ -55,155 +55,166 @@ const contextMenuList = [
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@connect(({ app }) => ({ app }))
|
||||
export default class PostCard extends React.Component {
|
||||
export default class PostCard extends React.PureComponent {
|
||||
state = {
|
||||
visibleMoreMenu: false,
|
||||
payload: this.props.payload,
|
||||
}
|
||||
|
||||
elementRef = React.createRef()
|
||||
|
||||
handleDispatchInvoke(key, payload) {
|
||||
this.props.dispatch({
|
||||
type: "app/ipcInvoke",
|
||||
payload: { key: key, payload: payload }
|
||||
})
|
||||
}
|
||||
|
||||
goElementById(id){
|
||||
document.getElementById(id).scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center",
|
||||
inline: "center"
|
||||
})
|
||||
}
|
||||
handleDispatchInvoke(key, payload) {
|
||||
this.props.dispatch({
|
||||
type: "app/ipcInvoke",
|
||||
payload: { key: key, payload: payload }
|
||||
})
|
||||
}
|
||||
|
||||
toogleMoreMenu(){
|
||||
this.setState({ visibleMoreMenu: !this.state.visibleMoreMenu })
|
||||
}
|
||||
goElementById(id) {
|
||||
document.getElementById(id).scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center",
|
||||
inline: "center"
|
||||
})
|
||||
}
|
||||
|
||||
renderReportedPost(){
|
||||
if(this.state.ReportIgnore) return null
|
||||
return (
|
||||
<div className={styles.post_card_flaggedWarning}>
|
||||
<Icons.FlagOutlined />
|
||||
<h3>It seems that this post has been reported</h3>
|
||||
<p>The content may be inappropriate or compromising</p>
|
||||
<antd.Button
|
||||
onClick={() => {
|
||||
this.setState({ ReportIgnore: true })
|
||||
}}
|
||||
>
|
||||
Ignore
|
||||
toogleMoreMenu() {
|
||||
this.setState({ visibleMoreMenu: !this.state.visibleMoreMenu })
|
||||
}
|
||||
|
||||
renderReportedPost() {
|
||||
if (this.state.ReportIgnore) return null
|
||||
return (
|
||||
<div className={styles.post_card_flaggedWarning}>
|
||||
<Icons.FlagOutlined />
|
||||
<h3>It seems that this post has been reported</h3>
|
||||
<p>The content may be inappropriate or compromising</p>
|
||||
<antd.Button
|
||||
onClick={() => {
|
||||
this.setState({ ReportIgnore: true })
|
||||
}}
|
||||
>
|
||||
Ignore
|
||||
</antd.Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderPost(data){
|
||||
const {
|
||||
id,
|
||||
post_time,
|
||||
postText,
|
||||
postFile,
|
||||
publisher,
|
||||
post_likes,
|
||||
is_post_pinned,
|
||||
is_liked,
|
||||
post_comments,
|
||||
get_post_comments
|
||||
} = data || defaultPayload
|
||||
|
||||
return(
|
||||
<>
|
||||
{this.state.postReported? this.renderReportedPost() : null}
|
||||
<div className={classnames(styles.post_include, {[styles.blur]: this.state.ReportIgnore? false : this.state.postReported })}>
|
||||
<Meta
|
||||
avatar={
|
||||
<div className={styles.postAvatar}>
|
||||
<antd.Avatar shape="square" size={50} src={publisher.avatar} />
|
||||
</div>
|
||||
}
|
||||
title={
|
||||
<div className={styles.post_card_title}>
|
||||
<h4 onClick={() => router.goProfile(publisher.username)} className={styles.titleUser}>
|
||||
@{publisher.username}
|
||||
{core.booleanFix(publisher.verified)? (<Icon style={{ color: 'blue' }} component={Icons.verifiedBadge} />) : null}
|
||||
{core.booleanFix(publisher.nsfw_flag)? (<antd.Tag style={{ margin: '0 0 0 13px' }} color="volcano" > NSFW </antd.Tag> ) : null}
|
||||
</h4>
|
||||
<div className={styles.PostTags}>
|
||||
<div className={styles.MoreMenu}>
|
||||
<antd.Dropdown onVisibleChange={this.handleVisibleChange} visible={this.state.visibleMoreMenu} trigger={['click']}>
|
||||
<Icons.MoreOutlined key="actionMenu" />
|
||||
</antd.Dropdown>
|
||||
</div>
|
||||
{core.booleanFix(is_post_pinned)? (<Icons.PushpinFilled />) : null}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
description={<span className={styles.textAgo}>{post_time}</span>}
|
||||
bordered="false"
|
||||
/>
|
||||
{postText ? (
|
||||
<div className={styles.post_card_content}>
|
||||
<h3 dangerouslySetInnerHTML={{ __html: postText }} />
|
||||
</div>
|
||||
) : null}
|
||||
{postFile ? (
|
||||
<div className={styles.post_card_file}>
|
||||
<MediaPlayer file={postFile} />
|
||||
</div>
|
||||
) : null}
|
||||
<div className={styles.ellipsisIcon}>
|
||||
<Icons.EllipsisOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.contextMenu.addEventListener(
|
||||
{
|
||||
priority: 100,
|
||||
onEventRender: contextMenuList,
|
||||
ref: this.elementRef.current,
|
||||
props: { id: this.state.payload.id }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
//
|
||||
|
||||
const actions = [
|
||||
<LikeBtn count={this.state.payload.post_likes} liked={core.booleanFix(this.state.payload.is_liked)} />,
|
||||
<Icons.Share2 />,
|
||||
<antd.Badge dot={this.state.payload.post_comments > 0 ? true : false}>
|
||||
<Icons.MessageSquare key="comments" />
|
||||
</antd.Badge>,
|
||||
]
|
||||
|
||||
return (
|
||||
<div ref={this.elementRef} key={this.state.payload.id} id={this.state.payload.id} className={styles.post_card_wrapper}>
|
||||
<antd.Card
|
||||
className={settings("post_hidebar") ? null : styles.showMode}
|
||||
onDoubleClick={() => null}
|
||||
onClick={() => this.goElementById(this.state.payload.id)}
|
||||
// onContextMenu={(e) => {
|
||||
// e.stopPropagation()
|
||||
// e.preventDefault()
|
||||
// window.contextMenu.open({ xPos: e.clientX, yPos: e.clientY, renderList: contextMenuList, id: this.state.payload.id })
|
||||
// }}
|
||||
actions={actions}
|
||||
hoverable
|
||||
>
|
||||
{this.renderPost(this.state.payload)}
|
||||
</antd.Card>
|
||||
renderContent(payload) {
|
||||
return (
|
||||
<div>
|
||||
{payload.postText ? (
|
||||
<div className={styles.post_card_content}>
|
||||
<h3 dangerouslySetInnerHTML={{ __html: payload.postText }} />
|
||||
</div>
|
||||
)
|
||||
) : null}
|
||||
{payload.postFile ? (
|
||||
<div className={styles.post_card_file}>
|
||||
<MediaPlayer file={payload.postFile} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.contextMenu.addEventListener(
|
||||
{
|
||||
priority: 100,
|
||||
onEventRender: contextMenuList,
|
||||
ref: this.elementRef.current,
|
||||
props: { id: this.state.payload.id }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
handleLikeClick = (id) => {
|
||||
if (typeof (this.props.handleActions)) {
|
||||
this.props.handleActions("like", id, (callback) => {
|
||||
let updated = this.state.payload
|
||||
if (callback.code == 200) {
|
||||
updated.is_liked = !this.state.payload.is_liked
|
||||
updated.post_likes = callback.response.count ?? 0
|
||||
this.setState({ payload: updated })
|
||||
} else {
|
||||
verbosity(`Api error response ${callback.code}`)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
verbosity(`socket connection not available`)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
id,
|
||||
post_time,
|
||||
postText,
|
||||
postFile,
|
||||
publisher,
|
||||
post_likes,
|
||||
is_post_pinned,
|
||||
is_liked,
|
||||
post_comments,
|
||||
get_post_comments
|
||||
} = this.state.payload || defaultPayload
|
||||
|
||||
const actions = [
|
||||
<LikeBtn handleClick={() => { this.handleLikeClick(id) }} count={post_likes} liked={core.booleanFix(is_liked)} />,
|
||||
<antd.Badge dot={this.state.payload.post_comments > 0 ? true : false}>
|
||||
<Icons.MessageSquare key="comments" />
|
||||
</antd.Badge>,
|
||||
]
|
||||
|
||||
return (
|
||||
<div ref={this.elementRef} key={this.state.payload.id} id={this.state.payload.id} className={styles.post_card_wrapper}>
|
||||
<antd.Card
|
||||
className={settings("post_hidebar") ? null : styles.showMode}
|
||||
onClick={() => this.goElementById(this.state.payload.id)}
|
||||
actions={actions}
|
||||
hoverable
|
||||
>
|
||||
{this.state.postReported ? this.renderReportedPost() : null}
|
||||
<div className={classnames(styles.post_include, { [styles.blur]: this.state.ReportIgnore ? false : this.state.postReported })}>
|
||||
<Meta
|
||||
avatar={
|
||||
<div className={styles.postAvatar}>
|
||||
<antd.Avatar shape="square" size={50} src={publisher.avatar} />
|
||||
</div>
|
||||
}
|
||||
title={
|
||||
<div className={styles.post_card_title}>
|
||||
<h4 onClick={() => router.goProfile(publisher.username)} className={styles.titleUser}>
|
||||
@{publisher.username}
|
||||
{core.booleanFix(publisher.verified) ? (<Icon style={{ color: 'blue' }} component={Icons.verifiedBadge} />) : null}
|
||||
{core.booleanFix(publisher.nsfw_flag) ? (<antd.Tag style={{ margin: '0 0 0 13px' }} color="volcano" > NSFW </antd.Tag>) : null}
|
||||
</h4>
|
||||
<div className={styles.PostTags}>
|
||||
<div className={styles.MoreMenu}>
|
||||
<antd.Dropdown onVisibleChange={this.handleVisibleChange} visible={this.state.visibleMoreMenu} trigger={['click']}>
|
||||
<Icons.MoreOutlined key="actionMenu" />
|
||||
</antd.Dropdown>
|
||||
</div>
|
||||
{core.booleanFix(is_post_pinned) ? (<Icons.PushpinFilled />) : null}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
description={<span className={styles.textAgo}>{post_time}</span>}
|
||||
bordered="false"
|
||||
/>
|
||||
{this.renderContent(this.state.payload)}
|
||||
<div className={styles.ellipsisIcon}>
|
||||
<Icons.EllipsisOutlined />
|
||||
</div>
|
||||
<div className={styles.likesIndicator} >
|
||||
{post_likes} likes
|
||||
</div>
|
||||
</div>
|
||||
</antd.Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -17,6 +17,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
.likesIndicator{
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left:0;
|
||||
background-color: #242424;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
transform: translate(0, -15px);
|
||||
padding: 5px 12px;
|
||||
}
|
||||
|
||||
.post_card_wrapper {
|
||||
user-select: none;
|
||||
box-shadow: @post_card_wrapper_shadow;
|
||||
@ -131,7 +145,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.post_card_title {
|
||||
display: flex;
|
||||
|
||||
|
@ -196,6 +196,7 @@ export function urlToBase64(url, callback) {
|
||||
reader.readAsDataURL(xhr.response);
|
||||
};
|
||||
xhr.open('GET', url);
|
||||
xhr.setRequestHeader('Access-Control-Allow-Headers', 'Access-Control-Allow-Origin');
|
||||
xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
|
@ -61,12 +61,15 @@ export default {
|
||||
*resetHeader({ }, { put }) {
|
||||
yield put({ type: "createNodeSocket" })
|
||||
},
|
||||
*use({ scope, invoke, query }, { put, select }) {
|
||||
*use({ scope, invoke, query, persistent, then }, { put, select }) {
|
||||
const state = yield select(state => state)
|
||||
if (!scope || !invoke || !query) {
|
||||
if (!scope) {
|
||||
verbosity(`some params is missing`)
|
||||
return false
|
||||
}
|
||||
if (typeof(persistent) == "undefined" ) {
|
||||
persistent = false
|
||||
}
|
||||
if (!state.socket.nodes[scope] && scope !== state.socket.headerNode) {
|
||||
let opt = {
|
||||
namespaceOrigin: `/${scope}`,
|
||||
@ -81,11 +84,18 @@ export default {
|
||||
connector: state.app.dispatcher,
|
||||
payload: opt,
|
||||
then: (socket) => {
|
||||
socket._emit(invoke, query.payload, (callback) =>{
|
||||
new Promise((resolve, reject) => resolve(query.callback(callback))).then(() => {
|
||||
socket.remove()
|
||||
if (typeof(then) !== "undefined") {
|
||||
then(socket)
|
||||
}
|
||||
if (typeof(query) !== "undefined") {
|
||||
socket._emit(invoke, query.payload, (callback) =>{
|
||||
new Promise((resolve, reject) => resolve(query.callback(callback))).then(() => {
|
||||
if (!persistent) {
|
||||
socket.remove()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
|
@ -13,67 +13,95 @@ import styles from './index.less'
|
||||
export default class Explore extends React.Component {
|
||||
|
||||
state = {
|
||||
socket: null,
|
||||
feed: null,
|
||||
renderError: false
|
||||
}
|
||||
|
||||
request(){
|
||||
this.props.dispatch({
|
||||
type: "socket/use",
|
||||
scope: "posts",
|
||||
invoke: "get",
|
||||
query: {
|
||||
payload: {
|
||||
from: "feed",
|
||||
userToken: this.props.app.session_token
|
||||
},
|
||||
callback: (data) => {
|
||||
if (Array.isArray(data.response)) {
|
||||
this.setState({ feed: data.response })
|
||||
}else{
|
||||
verbosity([`error gathering posts >`, data])
|
||||
this.setState({ renderError: true })
|
||||
}
|
||||
fetchFeed() {
|
||||
const { socket } = this.state
|
||||
if (socket) {
|
||||
const requestPayload = {
|
||||
from: "feed",
|
||||
userToken: this.props.app.session_token
|
||||
}
|
||||
|
||||
const requestCallback = (data) => {
|
||||
if (Array.isArray(data.response)) {
|
||||
this.setState({ feed: data.response })
|
||||
} else {
|
||||
verbosity([`error gathering posts >`, data])
|
||||
this.setState({ renderError: true })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
socket._emit("get", requestPayload, requestCallback)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
if(this.props.app.session_valid){
|
||||
this.request()
|
||||
handlePostActions(action, post_id, callback) {
|
||||
const { socket } = this.state
|
||||
if (socket) {
|
||||
const requestPayload = {
|
||||
userToken: this.props.app.session_token,
|
||||
post_id,
|
||||
action
|
||||
}
|
||||
|
||||
socket._emit("actions", requestPayload, (res) => callback(res))
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.app.session_valid) {
|
||||
this.props.dispatch({
|
||||
type: "socket/use",
|
||||
persistent: true,
|
||||
scope: "posts",
|
||||
then: (data) => {
|
||||
this.setState({ socket: data })
|
||||
this.fetchFeed()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.state.socket) {
|
||||
this.state.socket.remove()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if(!this.props.app.session_valid){
|
||||
if (!this.props.app.session_valid) {
|
||||
return <Invalid type="SESSION_INVALID" />
|
||||
}
|
||||
|
||||
if (!this.state.feed){
|
||||
return (
|
||||
<antd.Card bordered="false" >
|
||||
<antd.Skeleton active />
|
||||
</antd.Card>
|
||||
)
|
||||
if (!this.state.feed) {
|
||||
return (
|
||||
<antd.Card bordered="false" >
|
||||
<antd.Skeleton active />
|
||||
</antd.Card>
|
||||
)
|
||||
}
|
||||
|
||||
if (this.state.renderError){
|
||||
if (this.state.renderError) {
|
||||
return (
|
||||
<Invalid type="SESSION_INVALID" />
|
||||
)
|
||||
}
|
||||
|
||||
return(
|
||||
return (
|
||||
<div className={styles.exploreWrapper}>
|
||||
<List
|
||||
//loadMore={loadMore}
|
||||
dataSource={this.state.feed}
|
||||
renderItem={item => (
|
||||
<PostCard payload={item}/>
|
||||
)}
|
||||
//loadMore={loadMore}
|
||||
dataSource={this.state.feed}
|
||||
renderItem={item => (
|
||||
<PostCard handleActions={(...context) => this.handlePostActions(...context)} payload={item} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,6 @@ export default class BackgroundImage extends ThemeConfigurator {
|
||||
<h4 style={{ color: this.schemeToRGB(this.state.accentColor) }}>Sample text</h4>
|
||||
<p style={{ color: this.schemeToRGB(this.state.textColor) }}>Some text here</p>
|
||||
<p style={{ color: this.schemeToRGB(this.state.accentColor) }}>Some text here</p>
|
||||
|
||||
</div>
|
||||
<img style={{ opacity: this.state.model.opacity }} src={this.state.model.src} />
|
||||
</div> : <h3 style={{ textAlign: 'center' }} > No Background </h3>}
|
||||
|
@ -26,6 +26,7 @@
|
||||
.background_image_preview{
|
||||
position: relative;
|
||||
height: 50%;
|
||||
border-radius: 8px;
|
||||
|
||||
img{
|
||||
z-index: 9;
|
||||
|
Loading…
x
Reference in New Issue
Block a user