This commit is contained in:
srgooglo 2020-03-05 20:17:00 +01:00
parent fc6a25ddaa
commit 56259e3fbc
28 changed files with 603 additions and 459 deletions

View File

@ -1,5 +1,6 @@
module.exports = { module.exports = {
Endpoints: { Endpoints: {
follow_user: "https://api.ragestudio.net/RSA-COMTY/yid/follow-user?access_token=",
action_post: "https://api.ragestudio.net/RSA-COMTY/yid/post-actions?access_token=", action_post: "https://api.ragestudio.net/RSA-COMTY/yid/post-actions?access_token=",
get_posts: "https://api.ragestudio.net/RSA-COMTY/yid/posts?access_token=", get_posts: "https://api.ragestudio.net/RSA-COMTY/yid/posts?access_token=",
find_user: "https://api.ragestudio.net/RSA-COMTY/yid/find_user?access_token=", find_user: "https://api.ragestudio.net/RSA-COMTY/yid/find_user?access_token=",

View File

@ -2,7 +2,7 @@
"name": "comty-development", "name": "comty-development",
"title": "Comty™", "title": "Comty™",
"DevBuild": true, "DevBuild": true,
"version": "0.2.03", "version": "0.2.05",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"author": "RageStudio", "author": "RageStudio",
@ -15,7 +15,7 @@
"@material-ui/icons": "^4.9.1", "@material-ui/icons": "^4.9.1",
"@steveeeie/react-page-transition": "^1.1.2", "@steveeeie/react-page-transition": "^1.1.2",
"ant-design-pro": "^2.3.2", "ant-design-pro": "^2.3.2",
"antd": "^4.0.0", "antd": "^4.0.1",
"autoprefixer": "9.7.4", "autoprefixer": "9.7.4",
"axios": "^0.19.2", "axios": "^0.19.2",
"babel-core": "7.0.0-bridge.0", "babel-core": "7.0.0-bridge.0",

View File

@ -2,6 +2,28 @@ import * as ycore from 'ycore'
var jquery = require("jquery"); var jquery = require("jquery");
import * as Icons from '@ant-design/icons' import * as Icons from '@ant-design/icons'
export function follow_user(id, callback) {
let formdata = new FormData();
formdata.append("user_id", id);
formdata.append("server_key", ycore.yConfig.server_key);
const requestOptions = {
method: 'POST',
body: formdata,
redirect: 'follow'
};
ycore.DevOptions.ShowFunctionsLogs? console.log(`Following user => ${id} `) : null
const urlObj = `${ycore.endpoints.follow_user}${ycore.GetUserToken.decrypted().UserToken}`
fetch(urlObj, requestOptions)
.then(response => {
ycore.DevOptions.ShowFunctionsLogs? console.log(response) : null
return callback(false, response)
})
.catch(error => {
console.log('error', error)
return callback(true, error)
});
}
export const GetPostPrivacy = { export const GetPostPrivacy = {
bool: (e) => { bool: (e) => {
switch (e) { switch (e) {
@ -39,12 +61,12 @@ export function PublishPost(privacy, raw, file, callback){
if(!rawtext){ if(!rawtext){
return null return null
} }
console.log(privacy)
let formdata = new FormData(); let formdata = new FormData();
formdata.append("user_id", ycore.GetUserToken.decrypted().UserID); formdata.append("user_id", ycore.GetUserToken.decrypted().UserID);
formdata.append("server_key", ycore.yConfig.server_key); formdata.append("server_key", ycore.yConfig.server_key);
formdata.append("postPrivacy", privacy) formdata.append("postPrivacy", privacy)
formdata.append("postText", raw); formdata.append("postText", raw);
file? formdata.append("postPhotos", file) : null
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
body: formdata, body: formdata,

View File

@ -5,12 +5,15 @@ class CoreLoader extends React.PureComponent {
const { type } = this.props; const { type } = this.props;
if ( type == 'circle') { if ( type == 'circle') {
return ( return (
<div> <div className={style.newloader}>
<div className={style.loader}> <div></div>
<svg viewBox="0 0 80 80"> <div></div>
<circle id="test" cx="40" cy="40" r="32"></circle> <div></div>
</svg> <div></div>
</div> <div></div>
<div></div>
<div></div>
<div></div>
</div> </div>
); );
} }

View File

@ -136,3 +136,6 @@ html {
box-sizing: border-box; box-sizing: border-box;
} }
} }

View File

@ -55,12 +55,13 @@ class Sider extends PureComponent {
return theme return theme
} }
handleClickMenu = e => { handleClickMenu = e => {
e.key === 'SignOut' && ycore.LogoutCall() e.key === 'SignOut' && ycore.LogoutCall()
e.key === 'general_settings' && ycore.crouter.native('settings') e.key === 'general_settings' && ycore.crouter.native('settings')
e.key === 'accountpage' && router.push('/account') e.key === 'accountpage' && router.push('/account')
e.key === 'explore' && router.push('main')
} }
isDarkMode(){ isDarkMode(){
const { theme } = this.props const { theme } = this.props
if (theme == 'dark'){ if (theme == 'dark'){
@ -104,16 +105,6 @@ class Sider extends PureComponent {
<Icons.CompassOutlined /> <Icons.CompassOutlined />
<Trans><span>Explore</span></Trans> <Trans><span>Explore</span></Trans>
</antd.Menu.Item> </antd.Menu.Item>
{ycore.booleanFix(userData.is_pro)?
<antd.Menu.Item key="boosted_pages">
<Icons.ThunderboltOutlined />
<Trans><span>Boost</span></Trans>
</antd.Menu.Item>
:
<antd.Menu.Item key="upgrade_pro">
<Icons.StarOutlined/>
<Trans><span>PRO</span></Trans>
</antd.Menu.Item>}
<antd.Menu.Item key="general_settings"> <antd.Menu.Item key="general_settings">
<Icons.SettingOutlined/> <Icons.SettingOutlined/>
<Trans><span>Settings</span></Trans> <Trans><span>Settings</span></Trans>
@ -150,7 +141,7 @@ class Sider extends PureComponent {
</antd.Menu.Item> </antd.Menu.Item>
</antd.Menu> </antd.Menu>
<div className={styles.siderhead}> <div className={styles.siderhead}>
<antd.Avatar size={collapsed? "small" : "large"} shape={collapsed? "circle" : "square"} src={userData.avatar} className={collapsed? styles.avatar : styles.avatarFull} /> <antd.Avatar onClick={() => ycore.crouter.native(`@${userData.username}`)} size={collapsed? "small" : "large"} shape={collapsed? "circle" : "square"} src={userData.avatar} className={collapsed? styles.avatar : styles.avatarFull} />
</div> </div>
{collapsed? null : <div className={styles.userInfo}><a onClick={() => ycore.crouter.native(`@${userData.username}`)} ><h2>@{userData.username}</h2></a></div> } {collapsed? null : <div className={styles.userInfo}><a onClick={() => ycore.crouter.native(`@${userData.username}`)} ><h2>@{userData.username}</h2></a></div> }
</div> </div>

View File

@ -93,6 +93,7 @@
} }
} }
.siderhead{ .siderhead{
cursor: pointer;
font-family: 'Source Sans Pro', sans-serif; font-family: 'Source Sans Pro', sans-serif;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -10,7 +10,16 @@ const Loader = ({ spinning = true, fullScreen }) => {
return ( return (
<div className={styles.loader}> <div className={styles.loader}>
<div className={styles.warpper}> <div className={styles.warpper}>
<CoreLoader type='circle' /> <div className={styles.newloader}>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div> </div>
</div> </div>
) )
@ -23,7 +32,16 @@ const Loader = ({ spinning = true, fullScreen }) => {
})} })}
> >
<div className={styles.warpper}> <div className={styles.warpper}>
<CoreLoader type='circle' /> <div className={classNames(styles.newloader, {[styles.end]: !spinning}) }>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div> </div>
</div> </div>
) )

View File

@ -1,6 +1,6 @@
@import '~themes/vars.less'; @import '~themes/vars.less';
.loader { .loader {
background-color: rgba(255, 255, 255, 0.945); background-color: transparent; //rgba(44, 44, 44, 0.74);
width: 100%; width: 100%;
position: absolute; position: absolute;
top: 0; top: 0;
@ -16,6 +16,12 @@
position: fixed; position: fixed;
} }
&.hidden{
z-index: -1;
opacity: 0;
transition: opacity 3s ease 0.5s, z-index 0.1s ease 1.5s;
}
.warpper { .warpper {
position: absolute; position: absolute;
right: 0; right: 0;
@ -26,44 +32,87 @@
justify-content: space-around; justify-content: space-around;
} }
.inner {
width: 40px;
height: 40px;
margin: 0 auto;
text-indent: -12345px;
border-top: 1px solid rgba(0, 0, 0, 0.08);
border-right: 1px solid rgba(0, 0, 0, 0.08);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
border-left: 1px solid rgba(0, 0, 0, 0.7);
border-radius: 50%;
z-index: 100001;
:local { .newloader {
animation: spinner 600ms infinite linear; transform: scale(0.4);
width: 0px;
height: 0px;
margin: 0 auto;
position: relative;
&.end{
.loader {
z-index: -1;
opacity: 0;
}
>div {
animation: newloader 0.8s linear;
}
}
}
.newloader > div {
background-color: rgb(34, 34, 34);
width: 6px;
height: 20px;
position: absolute;
left: -10px;
bottom: 15px;
border-radius: 5px;
transform-origin: 10px 35px;
transform: rotate(0deg);
animation: newloader 0.8s infinite;
}
.newloader > div:nth-child(2) {
transform: rotate(45deg);
animation-delay: 0.1s;
}
.newloader > div:nth-child(3) {
transform: rotate(90deg);
animation-delay: 0.2s;
}
.newloader > div:nth-child(4) {
transform: rotate(135deg);
animation-delay: 0.3s;
}
.newloader > div:nth-child(5) {
transform: rotate(180deg);
animation-delay: 0.4s;
}
.newloader > div:nth-child(6) {
transform: rotate(225deg);
animation-delay: 0.5s;
}
.newloader > div:nth-child(7) {
transform: rotate(270deg);
animation-delay: 0.6s;
}
.newloader > div:nth-child(8) {
transform: rotate(315deg);
animation-delay: 0.7s;
}
@keyframes unshow {
0%{
opacity: 1;
}
100%{
opacity: 0;
z-index: -1;
} }
} }
@keyframes newloader {
.text { 0% {
width: 100px; background: transparent;
height: 20px; left: -10px;
text-align: center; transform-origin: 10px 35px;
font-size: 12px; }
letter-spacing: 4px; 30% {
color: #000; background: #fff;
} }
100% {
&.hidden { background: transparent;
z-index: -1; left: 10px;
opacity: 0; transform-origin: -10px 35px;
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s; }
} }
} }
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -57,7 +57,7 @@ class PostCard extends React.PureComponent{
} }
render(){ render(){
const { payload, customActions, } = this.props const { payload, customActions } = this.props
const { id, user, ago, avatar, content, file, postFileName, publisher, post_likes, is_post_pinned, is_liked } = payload || emptyPayload; const { id, user, ago, avatar, content, file, postFileName, publisher, post_likes, is_post_pinned, is_liked } = payload || emptyPayload;
const defaultActions = [<div><LikeBTN count={post_likes} id={id} liked={ycore.booleanFix(is_liked)? true : false} key="like" /></div>,<Icons.ShareAltOutlined key="share" />,<Icons.MoreOutlined key="actionMenu" />] const defaultActions = [<div><LikeBTN count={post_likes} id={id} liked={ycore.booleanFix(is_liked)? true : false} key="like" /></div>,<Icons.ShareAltOutlined key="share" />,<Icons.MoreOutlined key="actionMenu" />]
const actions = customActions || defaultActions; const actions = customActions || defaultActions;

View File

@ -11,18 +11,11 @@ const { Meta } = antd.Card;
const userData = ycore.SDCP(); const userData = ycore.SDCP();
const fileList = []; function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
const UploadProps = { reader.readAsDataURL(img);
name:'file', }
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
multiple: true,
listType: 'picture',
defaultFileList: [...fileList],
className: 'upload-list-inline',
};
export function HandleVisibility(){ export function HandleVisibility(){
@ -42,67 +35,75 @@ class PostCreator extends React.PureComponent{
posting: false, posting: false,
posting_ok: false, posting_ok: false,
shareWith: 'any', shareWith: 'any',
UploadActive: false,
} }
} }
ToogleVisibility(){ ToogleVisibility(){
this.setState({ visible: !this.state.visible }) this.setState({ visible: !this.state.visible })
} }
renderPostPlayer(payload){
const ident = payload ToogleUpload(){
if (ident.includes('.mp4')) { this.setState({ UploadActive: !this.state.UploadActive })
return (
<video id="player" playsinline controls >
<source src={payload} type="video/mp4"/>
</video>
)
}
if (ident.includes('.webm')) {
return (
<video id="player" playsinline controls >
<source src={payload} type="video/webm"/>
</video>
)
}
if (ident.includes('.mp3')){
return (
<audio id="player" controls>
<source src={payload} type="audio/mp3" />
</audio>
)
}
if (ident.includes('.ogg')){
return (
<audio id="player" controls>
<source src={payload} type="audio/ogg" />
</audio>
)
}
else {
return (
<img src={payload} />
)
}
} }
handleFileUpload = info => {
console.log('handle')
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl =>
this.setState({
imageUrl,
loading: false,
}),
);
}
};
beforeUpload(file) {
console.log('before')
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
}
handleChanges = ({ target: { value } }) => { handleChanges = ({ target: { value } }) => {
this.setState({ rawtext: value, keys_remaining: (ycore.DevOptions.MaxLengthPosts - value.length) }) this.setState({ rawtext: value, keys_remaining: (ycore.DevOptions.MaxLengthPosts - value.length) })
} }
handleKeysProgressBar(){ handleKeysProgressBar(){
const { keys_remaining } = this.state; const { keys_remaining } = this.state;
if (keys_remaining <= 80) { if (keys_remaining <= 80) {
return 'exception' return 'exception'
}else return('active') }else return('active')
} }
handleToggleToolbox = () =>{ handleToggleToolbox = () =>{
this.setState({ toolbox_open: !this.state.toolbox_open }) this.setState({ toolbox_open: !this.state.toolbox_open })
} }
HandlePublishPost = (e) => {
const { rawtext, shareWith, postFile} = this.state; handlePublishPost = (e) => {
const { rawtext, shareWith, imageUrl} = this.state;
let postFile;
if (imageUrl) {
console.log('EXIST ',imageUrl)
postFile = imageUrl;
}
if(!rawtext){ if(!rawtext){
return null return null
} }
this.setState({ posting: true, keys_remaining: '512' }) this.setState({ posting: true, keys_remaining: '512' })
console.log('to post ',postFile)
ycore.PublishPost(ycore.GetPostPrivacy.bool(shareWith), rawtext, postFile, (err, res) => { ycore.PublishPost(ycore.GetPostPrivacy.bool(shareWith), rawtext, postFile, (err, res) => {
if (err) { if (err) {
ycore.notifyError(err) ycore.notifyError(err)
@ -113,13 +114,15 @@ class PostCreator extends React.PureComponent{
RefreshFeed() RefreshFeed()
}) })
} }
render(){ render(){
const { keys_remaining, visible } = this.state; const { keys_remaining, visible } = this.state;
const percent = (((keys_remaining/ycore.DevOptions.MaxLengthPosts) * 100).toFixed(2) ) const percent = (((keys_remaining/ycore.DevOptions.MaxLengthPosts) * 100).toFixed(2) )
const changeShare = ({ key }) => { const changeShare = ({ key }) => {
this.setState({ shareWith: key }) this.setState({ shareWith: key })
} }
const shareOptionsMenu = ( const shareOptionsMenu = (
<antd.Menu onClick={changeShare}> <antd.Menu onClick={changeShare}>
<antd.Menu.Item key="any">{ycore.GetPostPrivacy.decorator("any")}</antd.Menu.Item> <antd.Menu.Item key="any">{ycore.GetPostPrivacy.decorator("any")}</antd.Menu.Item>
@ -133,18 +136,35 @@ class PostCreator extends React.PureComponent{
<div className={styles.cardWrapper}> <div className={styles.cardWrapper}>
<antd.Card bordered="false"> <antd.Card bordered="false">
<div className={styles.inputWrapper}> <div className={styles.inputWrapper}>
<div className={styles.titleAvatar}><img src={userData.avatar} /></div> {this.state.UploadActive?
<antd.Input.TextArea disabled={this.state.posting? true : false} onPressEnter={this.HandlePublishPost} value={this.state.rawtext} autoSize={{ minRows: 3, maxRows: 5 }} dragable="false" placeholder="What are you thinking?" onChange={this.handleChanges} allowClear maxLength={ycore.DevOptions.MaxLengthPosts} rows={4} /> <antd.Upload.Dragger
<div><antd.Button disabled={this.state.posting? true : (keys_remaining < 512? false : true)} onClick={this.HandlePublishPost} type="primary" icon={this.state.posting_ok? <Icons.CheckCircleOutlined/> : (this.state.posting? <Icons.LoadingOutlined /> : <Icons.ExportOutlined /> )} /></div> multiple= {true}
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
beforeUpload={this.beforeUpload}
onChange={this.handleFileUpload}
>
<p className="ant-upload-drag-icon">
<Icons.InboxOutlined />
</p>
<p className="ant-upload-text">Click or drag file to this area to upload</p>
<p className="ant-upload-hint">
Support for a single or bulk upload.
</p>
</antd.Upload.Dragger>
:
<div>
<div className={styles.titleAvatar}><img src={userData.avatar} /></div>
<antd.Input.TextArea disabled={this.state.posting? true : false} onPressEnter={this.handlePublishPost} value={this.state.rawtext} autoSize={{ minRows: 3, maxRows: 5 }} dragable="false" placeholder="What are you thinking?" onChange={this.handleChanges} allowClear maxLength={ycore.DevOptions.MaxLengthPosts} rows={4} />
<div><antd.Button disabled={this.state.posting? true : (keys_remaining < 512? false : true)} onClick={this.handlePublishPost} type="primary" icon={this.state.posting_ok? <Icons.CheckCircleOutlined/> : (this.state.posting? <Icons.LoadingOutlined /> : <Icons.ExportOutlined /> )} /></div>
</div>}
</div> </div>
<div className={styles.progressHandler}><antd.Progress strokeWidth="4px" className={this.state.posting? styles.proccessUnset : (keys_remaining < 512? styles.proccessSet : styles.proccessUnset)} status={this.handleKeysProgressBar()} showInfo={false} percent={percent} /></div> <div className={styles.progressHandler}><antd.Progress strokeWidth="4px" className={this.state.posting? styles.proccessUnset : (keys_remaining < 512? styles.proccessSet : styles.proccessUnset)} status={this.handleKeysProgressBar()} showInfo={false} percent={percent} /></div>
<div className={styles.postExtra} > <div className={styles.postExtra} >
<antd.Upload {...UploadProps}>
<antd.Button type="ghost"> <Icons.CameraFilled /></antd.Button> <antd.Button type="ghost" onClick={() => this.ToogleUpload()} > <Icons.CameraFilled /></antd.Button>
</antd.Upload>
<antd.Button type="ghost"> <Icons.VideoCameraFilled /></antd.Button> <antd.Button type="ghost"> <Icons.VideoCameraFilled /></antd.Button>
<antd.Button onClick={this.handleToggleToolbox} type="ghost"><Icons.PlusCircleOutlined /></antd.Button> <antd.Button onClick={this.handleToggleToolbox} type="ghost"><Icons.PlusCircleOutlined /></antd.Button>
<antd.Dropdown overlay={shareOptionsMenu}> <antd.Dropdown overlay={shareOptionsMenu}>

View File

@ -158,6 +158,13 @@
} }
} }
.avatar-uploader > .ant-upload {
width: 128px;
height: 128px;
}
.proccessUnset{ .proccessUnset{
opacity: 0; opacity: 0;
transition: opacity 250ms linear; transition: opacity 250ms linear;
@ -168,6 +175,7 @@
transition: opacity 250ms linear; transition: opacity 250ms linear;
animation: proccessSet 250ms linear; animation: proccessSet 250ms linear;
} }
@keyframes proccessSet { @keyframes proccessSet {
0% { opacity: 0; } 0% { opacity: 0; }
100% { opacity: 1; } 100% { opacity: 1; }

View File

@ -0,0 +1,65 @@
import React from 'react'
import * as antd from 'antd'
import * as ycore from 'ycore'
import styles from './index.less'
import * as Icons from '@ant-design/icons';
import Icon from '@ant-design/icons'
import { CustomIcons } from 'components'
const userData = ycore.SDCP()
const { Meta } = antd.Card;
class SearchCard extends React.PureComponent{
render(){
const { source, } = this.props
const { username, avatar, about, id } = source;
const DevInfo = `ID #${id} | Dev ${ycore.booleanFix(source.dev)? 'yes' : 'no'} | `
const AdminInfo = `RID #${source.country_id} | IP ${source.ip_address} | `
const DataStrip = {
title: (e) => {
if( this.props.type == 'Users'){
return (`@${username}`)
}
if( this.props.type == 'Groups'){
return (`${source.name}`)
}
return null
},
description: (e) => {
if( this.props.type == 'Users'){
return (`${DevInfo}${AdminInfo}`)
}
if( this.props.type == 'Groups'){
return (`GID #${source.group_id} | Created ${source.registered} | CAT ID #${source.category_id} / ${source.category} |`)
}
return null
},
about: (e) => {
return( about )
}
}
return(
<div className={styles.cardWrapper}>
<antd.Card >
<Meta
avatar={<div className={styles.postAvatar}><antd.Avatar shape="square" size={50} src={avatar} /></div>}
title={
<div className={styles.titleWrapper} >
<h4 onClick={() => ycore.crouter.native(`@${username}`)} className={styles.titleUser}>{DataStrip.title()}</h4>
<antd.Tooltip title="User Verified">{ycore.booleanFix(source.verified)? <Icon style={{ color: 'blue', verticalAlign:'top' }} component={CustomIcons.VerifiedBadge} /> : null} </antd.Tooltip>
</div>}
description={ycore.booleanFix(userData.dev)? <span className={styles.textAgo}>{DataStrip.description()}</span> : null}
bordered="false"
/>
<div className={styles.postContent}> <h3 dangerouslySetInnerHTML={{__html: DataStrip.about() }} /> </div>
</antd.Card>
</div>
)
}
}
export default SearchCard

View File

@ -5,9 +5,8 @@
border-radius: 7px; border-radius: 7px;
max-width: 510px; max-width: 510px;
min-width: 265px; min-width: 265px;
margin: auto;
width: auto; width: auto;
margin: 23px 50px ; margin: 23px auto 50px auto;
:global{ :global{
.ant-card-meta-detail > div:not(:last-child){ .ant-card-meta-detail > div:not(:last-child){
margin: 0 margin: 0

View File

@ -1,48 +0,0 @@
import React from 'react'
import * as antd from 'antd'
import * as ycore from 'ycore'
import styles from './index.less'
import * as Icons from '@ant-design/icons';
import Icon from '@ant-design/icons'
const userData = ycore.SDCP()
const { Meta } = antd.Card;
// Set default by configuration
const emptyPayload = {user: 'User Unknown', ago: 'This User is empty', avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png', content: 'Test Test' }
class UserCard extends React.PureComponent{
constructor(props){
super(props),
this.state = {
}
}
render(){
const { source, } = this.props
const { username, avatar, about, id } = source || emptyPayload;
const DevInfo = `ID #${id} | Developer ${ycore.booleanFix(source.dev)? 'yes' : 'no'} |`
const AdminInfo = `Email ${source.email} | `
return(
<div className={styles.cardWrapper}>
<antd.Card >
<Meta
avatar={<div className={styles.postAvatar}><antd.Avatar shape="square" size={50} src={avatar} /></div>}
title={
<div className={styles.titleWrapper} >
<h4 onClick={() => ycore.crouter.native(`@${username}`)} className={styles.titleUser}>@{username} </h4>
</div>}
description={ycore.booleanFix(userData.dev)? <span className={styles.textAgo}>{DevInfo} {AdminInfo}</span> : null}
bordered="false"
/>
<div className={styles.postContent}> <h3>{about}</h3></div>
</antd.Card>
</div>
)
}
}
export default UserCard

View File

@ -0,0 +1,11 @@
import React from 'react'
import styles from './like_btn.scss'
import classnames from 'classnames'
export default class Like_btn extends React.Component{
render(){
return(
<a className={classnames(styles.like_btn, {[styles.nofollowed]: !this.props.followed})} ><span>{this.props.followed? 'Following' : 'Follow'}</span></a>
)
}
}

View File

@ -0,0 +1,57 @@
$width: 120px;
$height: 40px;
$border: 0;
$violet: #6559ae;
$orange: #ff7159;
$border-radius: 8px;
$deg: 120deg;
$size: 400%;
$dur: 15s;
@mixin clip-frame($width, $height, $border) {
-webkit-clip-path: polygon(0% 100%, $border 100%, $border $border, $width - $border $border, $width - $border $height - $border, $border $height - $border, $border 100%, 100% 100%, 100% 0%, 0% 0%);
}
.like_btn {
width: 100px;
height: 30px;
line-height: 28px;
padding: 5px 15px 5px 15px;
@extend .text-formatting;
&:hover {
color: #7e7e7e;
}
&.nofollowed{
&:hover {
border: none;
content: '';
color: white;
border-radius: $border-radius;
background: linear-gradient($deg, $violet, $orange, $violet);
background-size: $size $size;
animation: gradient $dur ease-in-out infinite, border 1s forwards ease-in-out reverse;
}
}
}
/* helpers */
.text-formatting {
text-decoration: none;
text-align: center;
vertical-align: middle;
letter-spacing: 1px;
}
/* motion */
@keyframes gradient {
0% { background-position: 14% 0%; }
50% { background-position: 87% 100%; }
100% { background-position: 14% 0%; }
}

View File

@ -7,6 +7,7 @@ import {CustomIcons, MainFeed} from 'components'
import { SetHeaderSearchType } from 'components/HeaderSearch' import { SetHeaderSearchType } from 'components/HeaderSearch'
import * as Icons from '@ant-design/icons'; import * as Icons from '@ant-design/icons';
import Icon from '@ant-design/icons' import Icon from '@ant-design/icons'
import Like_btn from './components/like_btn.js'
const userData = ycore.SDCP(); const userData = ycore.SDCP();
function isOwnProfile(id){ function isOwnProfile(id){
@ -17,45 +18,25 @@ function isOwnProfile(id){
return false return false
} }
const UserHeader = ({ values }) => {
return (
<div className={styles.userWrapper}>
<div className={styles.UserCover}>
<img src={values.cover} />
</div>
<PageHeaderWrapper content={
<div className={styles.pageHeaderContent}>
<div className={styles.avatar}>
<antd.Avatar shape="square" src={values.avatar} />
</div>
<div className={styles.content}>
<div className={styles.TagWrappers}>
{ycore.booleanFix(values.nsfw_flag)? <antd.Tag color="volcano" >NSFW</antd.Tag> : null}
</div>
<div className={styles.contentTitle}>
<h1 style={{ marginBottom: '0px' }} >{values.username}<antd.Tooltip title="User Verified">{ycore.booleanFix(values.verified)? <Icon style={{ color: 'blue', verticalAlign:'top' }} component={CustomIcons.VerifiedBadge} /> : null}</antd.Tooltip></h1>
<span style={{ fontSize: '14px', fontWeight: '100', lineHeight: '0', marginBottom: '5px' }} dangerouslySetInnerHTML={{__html: values.about }} />
</div>
</div>
</div>
} />
</div>
);
};
class UserProfile extends React.Component { class UserProfile extends React.Component {
constructor(props){ constructor(props){
super(props), super(props),
this.state = { this.state = {
UUID: '', UUID: '',
RenderValue: {}, RenderValue: {},
loading: true loading: true,
Followed: '',
} }
} }
handleFollowUser = () => {
ycore.follow_user(this.state.UUID, (exception, response)=>{
if(exception){return ycore.notifyError(exception) }
this.setState({Followed: !this.state.Followed})
return
})
}
componentDidMount(){ componentDidMount(){
const { regx } = this.props const { regx } = this.props
this.initUser(regx) this.initUser(regx)
@ -85,21 +66,52 @@ class UserProfile extends React.Component {
ycore.DevOptions.ShowFunctionsLogs ? console.log(`Using aproximate user! => ${c1} / ${c2}`) : null ycore.DevOptions.ShowFunctionsLogs ? console.log(`Using aproximate user! => ${c1} / ${c2}`) : null
ycore.crouter.native(`@${c1}`) ycore.crouter.native(`@${c1}`)
} }
this.setState({ UUID: rp['0'].user_id, RenderValue: rp['0'], loading: false }) this.setState({ UUID: rp['0'].user_id, RenderValue: rp['0'], loading: false , Followed: ycore.booleanFix(rp['0'].is_following)})
} catch (err) { } catch (err) {
ycore.notifyError(err) ycore.notifyError(err)
} }
}) })
} }
UserHeader = (values) => {
return (
<div className={styles.userWrapper}>
<div className={styles.UserCover}>
<img src={values.cover} />
</div>
<PageHeaderWrapper content={
<div className={styles.pageHeaderContent}>
<div className={styles.avatar}>
<antd.Avatar shape="square" src={values.avatar} />
</div>
<div className={styles.content}>
<div className={styles.TagWrappers}>
{ycore.booleanFix(values.nsfw_flag)? <antd.Tag color="volcano" >NSFW</antd.Tag> : null}
{ycore.booleanFix(values.is_pro)? <antd.Tag color="purple">CPRO <Icons.RocketOutlined /></antd.Tag> : null}
{ycore.booleanFix(values.dev)? <antd.Tag color="default">DEVELOPER <Icons.CodeOutlined /></antd.Tag> : null}
{isOwnProfile()? <div className={styles.follow_wrapper} onClick={() => this.handleFollowUser()} ><Like_btn followed={this.state.Followed? true : false} /></div> : null}
</div>
<div className={styles.contentTitle}>
<h1 style={{ marginBottom: '0px' }} >{values.username}<antd.Tooltip title="User Verified">{ycore.booleanFix(values.verified)? <Icon style={{ color: 'blue', verticalAlign:'top' }} component={CustomIcons.VerifiedBadge} /> : null}</antd.Tooltip></h1>
<span style={{ fontSize: '14px', fontWeight: '100', lineHeight: '0', marginBottom: '5px' }} dangerouslySetInnerHTML={{__html: values.about }} />
</div>
</div>
</div>
} />
</div>
);
};
render(){ render(){
const { loading, UUID} = this.state const { loading, UUID } = this.state
console.log(UUID) console.log(UUID)
return( return(
<div> <div>
{loading? <antd.Skeleton active /> : {loading? <antd.Skeleton active /> :
(<div> (<div>
<UserHeader values={this.state.RenderValue} /> {this.UserHeader(this.state.RenderValue)}
<MainFeed get='user' uid={UUID} /> <MainFeed get='user' uid={UUID} />
</div>) </div>)
} }

View File

@ -1,35 +1,5 @@
@import '~themes/vars.less'; @import '~themes/vars.less';
.userWrapper{
padding: 0 68px 15px 68px;
margin: auto;
:global{
.ant-page-header-content {
padding-top: 0;
overflow: initial !important;
}
.ant-page-header {
padding: 20px 0 3px 0;
}
}
}
.TagWrappers{
float: right;
position: relative;
}
.UserCover {
border-radius: 15px 15px 0 0;
position: relative;
width: 100%;
margin: -32px auto auto auto;
overflow: hidden;
max-height: 40%;
img{
width: 100%;
}
}
.textOverflow() { .textOverflow() {
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
@ -54,19 +24,52 @@
} }
} }
.activitiesList { .userWrapper{
padding: 0 24px 8px 24px; padding: 0 68px 15px 68px;
.username { margin: auto;
color: @text-color; :global{
} .ant-page-header-content {
.event { padding-top: 0;
font-weight: normal; overflow: initial !important;
}
.ant-page-header {
padding: 20px 0 3px 0;
}
.ant-pro-page-header-wrap-page-header-warp {
border-radius: 0 0 20px 20px;
}
} }
} }
.avatar { .TagWrappers{
transform: translate(-40px, -50px); width: 100%;
float: right;
position: relative;
margin: 0 0 7px 0 !important;
}
.UserCover {
border-radius: 15px 15px 0 0;
position: relative;
margin: -32px auto auto auto;
max-height: 400px;
overflow: hidden;
img{
width: calc(100% + 30px);
overflow: hidden;
margin: auto;
}
}
.follow_wrapper{
margin: 0 7px 0 7px;
position: relative;
float: right;
}
.avatar {
transform: translate(-25px, -45px);
& > span { & > span {
position: relative; position: relative;
z-index: 10; z-index: 10;
@ -75,6 +78,8 @@
} }
:global{ :global{
.ant-avatar { .ant-avatar {
box-shadow: 13px 13px 17px 4px rgba(69, 69, 69, 0.151);
border-radius: 7px;
img{ img{
width: 120px; width: 120px;
} }
@ -85,11 +90,12 @@
.pageHeaderContent { .pageHeaderContent {
vertical-align: top; vertical-align: top;
display: flex; display: flex;
.content { .content {
font-family: "Poppins", sans-serif; font-family: "Poppins", sans-serif;
color: @text-color-secondary; color: @text-color-secondary;
width: 100%;
.contentTitle { .contentTitle {
padding: 0 10px 10px 0;
color: @heading-color; color: @heading-color;
font-weight: 500; font-weight: 500;
font-size: 20px; font-size: 20px;
@ -98,159 +104,6 @@
} }
} }
.extraContent {
.clearfix();
float: right;
white-space: nowrap;
.statItem {
position: relative;
display: inline-block;
padding: 0 32px;
> p:first-child {
margin-bottom: 4px;
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
}
> p {
margin: 0;
color: @heading-color;
font-size: 30px;
line-height: 38px;
> span {
color: @text-color-secondary;
font-size: 20px;
}
}
&::after {
position: absolute;
top: 8px;
right: 0;
width: 1px;
height: 40px;
background-color: @border-color-split;
content: '';
}
&:last-child {
padding-right: 0;
&::after {
display: none;
}
}
}
}
.members {
a {
display: block;
height: 24px;
margin: 12px 0;
color: @text-color;
transition: all 0.3s;
.textOverflow();
.member {
margin-left: 12px;
font-size: @font-size-base;
line-height: 24px;
vertical-align: top;
}
&:hover {
color: @primary-color;
}
}
}
.projectList {
:global {
.ant-card-meta-description {
height: 44px;
overflow: hidden;
color: @text-color-secondary;
line-height: 22px;
}
}
.cardTitle {
font-size: 0;
a {
display: inline-block;
height: 24px;
margin-left: 12px;
color: @heading-color;
font-size: @font-size-base;
line-height: 24px;
vertical-align: top;
&:hover {
color: @primary-color;
}
}
}
.projectGrid {
width: 33.33%;
}
.projectItemContent {
display: flex;
height: 20px;
margin-top: 8px;
overflow: hidden;
font-size: 12px;
line-height: 20px;
.textOverflow();
a {
display: inline-block;
flex: 1 1 0;
color: @text-color-secondary;
.textOverflow();
&:hover {
color: @primary-color;
}
}
.datetime {
flex: 0 0 auto;
float: right;
color: @disabled-color;
}
}
}
.datetime {
color: @disabled-color;
}
@media screen and (max-width: @screen-xl) and (min-width: @screen-lg) {
.activeCard {
margin-bottom: 24px;
}
.members {
margin-bottom: 0;
}
.extraContent {
margin-left: -44px;
.statItem {
padding: 0 16px;
}
}
}
@media screen and (max-width: @screen-lg) {
.activeCard {
margin-bottom: 24px;
}
.members {
margin-bottom: 0;
}
.extraContent {
float: none;
margin-right: 0;
.statItem {
padding: 0 16px;
text-align: left;
&::after {
display: none;
}
}
}
}
@media screen and (max-width: @screen-md) { @media screen and (max-width: @screen-md) {
.extraContent { .extraContent {
@ -286,13 +139,3 @@
} }
} }
.main_container {
width: 1200px;
margin-left: auto;
margin-right: auto;
}
.main_content {
padding: 10px 20px;
}

View File

@ -2,7 +2,7 @@ import CustomIcons from './CustomIcons'
import PageTransition from './PageTransition' import PageTransition from './PageTransition'
import MainFeed from './MainFeed' import MainFeed from './MainFeed'
import YulioID from './YulioID' import YulioID from './YulioID'
import UserCard from './UserCard' import SearchCard from './SearchCard'
import LikeBTN from './LikeBtn' import LikeBTN from './LikeBtn'
import UserProfile from './UserProfile' import UserProfile from './UserProfile'
import MainSidebar from './MainSidebar' import MainSidebar from './MainSidebar'
@ -16,4 +16,4 @@ import CoreLoader from './CoreLoader'
import MicroHeader from './MicroHeader' import MicroHeader from './MicroHeader'
import HeaderSearch from './HeaderSearch' import HeaderSearch from './HeaderSearch'
export { PageTransition, UserCard, HeaderSearch, YulioID, UserProfile, MyLayout, Loader, Page, ScrollBar, CoreLoader, PostCard, PostCreator, CustomIcons, MainSidebar, LikeBTN, MainFeed, MicroHeader} export { PageTransition, SearchCard, HeaderSearch, YulioID, UserProfile, MyLayout, Loader, Page, ScrollBar, CoreLoader, PostCard, PostCreator, CustomIcons, MainSidebar, LikeBTN, MainFeed, MicroHeader}

View File

@ -17,6 +17,7 @@ import styles from './PrimaryLayout.less'
const { Content } = Layout const { Content } = Layout
const { ChatSider, Sider, Control } = MyLayout const { ChatSider, Sider, Control } = MyLayout
const userData = ycore.SDCP()
@withRouter @withRouter
@ -175,9 +176,13 @@ class PrimaryLayout extends PureComponent {
<div id="secondaryLayout" className={styles.rightContainer}> <div id="secondaryLayout" className={styles.rightContainer}>
<PageTransition preset="moveToLeftFromRight" transitionKey={location.pathname}> <PageTransition preset="moveToLeftFromRight" transitionKey={location.pathname}>
<Fragment> <div className={styles.SecondHeader}>
{this.state.ContentSecondLayer} <div className={styles.notif_box}></div>
</Fragment> <img src={userData.avatar} />
</div>
<Fragment>
{this.state.ContentSecondLayer}
</Fragment>
</PageTransition> </PageTransition>
</div> </div>

View File

@ -1,5 +1,21 @@
@import '~themes/vars.less'; @import '~themes/vars.less';
.SecondHeader{
float: right;
display: flex;
img {
border-radius: 15px;
width: 40px;
}
.notif_box {
margin: 0 15px 0 5px;
width: 40px;
height: 40px;
border-radius: 15px;
background-color: #78CFED;
}
}
.mobilewarning{ .mobilewarning{
background-color: rgba(0, 0, 0, 0.975); background-color: rgba(0, 0, 0, 0.975);
color: white; color: white;
@ -118,7 +134,7 @@
.rightContainer{ .rightContainer{
background-color:#201F23; background-color:#201F23;
border-radius: 32px 0 0 32px; border-radius: 32px 0 0 32px;
padding: 15px 15px 15px 15px; padding: 20px 15px 15px 15px;
width: 27%; width: 27%;
height: 100vh; height: 100vh;
position: relative; position: relative;

14
src/pages/hamza/index.js Normal file
View File

@ -0,0 +1,14 @@
import React from 'react'
import * as ycore from 'ycore'
export default class Hamza extends React.PureComponent {
render() {
return (
<div>
<h1>
Españita Hola
</h1>
</div>
)
}
}

View File

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import { pathMatchRegexp } from 'utils' import { pathMatchRegexp } from 'utils'
import { UserCard } from 'components' import { SearchCard } from 'components'
import styles from './styles.less' import styles from './styles.less'
import * as ycore from 'ycore' import * as ycore from 'ycore'
import * as antd from 'antd' import * as antd from 'antd'
@ -9,8 +9,6 @@ import Icon from '@ant-design/icons'
const userData = ycore.SDCP() const userData = ycore.SDCP()
class SearchPageIndexer extends PureComponent { class SearchPageIndexer extends PureComponent {
constructor(props){ constructor(props){
super(props), super(props),
@ -43,43 +41,70 @@ class SearchPageIndexer extends PureComponent {
renderResult = (source) => { renderResult = (source) => {
try { try {
const Empty = (
<div>
<antd.Result
status="404"
title="Nothing..."
subTitle="Sorry, this does not exist."
/>
</div>
)
// TO DO: Settings serach & Post Search // TO DO: Settings serach & Post Search
const usersParsed = JSON.parse(source)['users'] const usersParsed = JSON.parse(source)['users']
const groupsParsed = JSON.parse(source)['groups'] const groupsParsed = JSON.parse(source)['groups']
const pagesParsed = JSON.parse(source)['pages'] const pagesParsed = JSON.parse(source)['pages']
if (usersParsed.length >= 1) {
const users = () => {if (usersParsed.length >= 1) {
console.log('Users => ', usersParsed) console.log('Users => ', usersParsed)
return( return this.EntryComponent('Users', usersParsed)
<div> }}
<antd.Typography.Title level={2} ><Icons.TeamOutlined /> Users </antd.Typography.Title> const groups = () => {if (groupsParsed.length >= 1) {
<div className={styles.searchEntry}> console.log('Groups => ', groupsParsed)
<antd.List return this.EntryComponent('Groups', groupsParsed)
grid={{ }}
gutter: 16, const pages = () => {if (pagesParsed.length >= 1) {
xs: 1, console.log('Pages => ', pagesParsed)
sm: 2, return this.EntryComponent('Pages', pagesParsed)
md: 4, }}
lg: 4,
xl: 6, if (!usersParsed.length >= 1 && !groupsParsed.length >= 1 && !pagesParsed.length >= 1){
xxl: 3, return Empty
}}
dataSource={usersParsed}
renderItem={item => (
<UserCard source={item} />
)}
/>
</div>
</div>
)
}
if (groupsParsed.length >= 1) {
return console.log('Groups => ', groupsParsed)
}
if (pagesParsed.length >= 1) {
return console.log('Pages => ', pagesParsed)
} }
return null return [users(), groups(), pages()]
} catch (error) {
console.log(error)
return <center><h2>Render Error</h2></center>
}
}
EntryComponent = (t, source) => {
try {
return(
<div>
<antd.Typography.Title level={2} ><Icons.TeamOutlined /> {t} </antd.Typography.Title>
<div className={styles.searchEntry}>
<antd.List
grid={{
gutter: 16,
xs: 1,
sm: 2,
md: 4,
lg: 4,
xl: 6,
xxl: 3,
}}
dataSource={source}
renderItem={item => (
<SearchCard type={t} source={item} />
)}
/>
</div>
</div>
)
} catch (error) { } catch (error) {
console.log(error) console.log(error)
return <center><h2>Render Error</h2></center> return <center><h2>Render Error</h2></center>

View File

@ -0,0 +1,20 @@
import React from 'react'
import styles from './about.less'
import * as ycore from 'ycore'
import * as antd from 'antd'
class AppAbout extends React.Component {
render(){
return(
<div className={styles.aboutWrapper}>
<img src={ycore.AppInfo.logo} />
<antd.Card >
<h1 className={styles.appName}> {ycore.AppInfo.name} </h1>
<antd.Tag color="geekblue">v{ycore.AppInfo.version}</antd.Tag>{ycore.DetectNoNStableBuild('TagComponent')}
</antd.Card>
</div>
)
}
}
export default AppAbout

View File

@ -0,0 +1,17 @@
.aboutWrapper{
margin: auto;
max-width: 70vw;
width: 500px;
vertical-align: middle;
position: relative;
background-color: rgba(73, 72, 72, 0.349);
img{
width: 100%;
padding: 15px;
}
}
.appName {
font-family: "Poppins", sans-serif;
font-size: 27px;
}

View File

@ -2,17 +2,21 @@ import React from 'react';
import { GridContent } from '@ant-design/pro-layout'; import { GridContent } from '@ant-design/pro-layout';
import { Icon as LegacyIcon } from '@ant-design/compatible'; import { Icon as LegacyIcon } from '@ant-design/compatible';
import { Menu, Typography } from 'antd'; import { Menu, Typography } from 'antd';
import * as antd from 'antd'
import * as ycore from 'ycore'
import styles from './style.less'; import styles from './style.less';
import NotificationView from './components/notification.js'; import NotificationView from './components/notification.js';
import SecurityView from './components/security.js'; import SecurityView from './components/security.js';
import Base from './components/base.js' import Base from './components/base.js'
import AppAbout from './components/about.js'
const { Item } = Menu; const { Item } = Menu;
const menuMap = { const menuMap = {
base: 'App', base: 'App',
security: 'Security', security: 'Security',
notification: 'Notification', notification: 'Notification',
about: 'App About'
}; };
const { Title } = Typography; const { Title } = Typography;
@ -44,6 +48,8 @@ class GeneralSettings extends React.Component {
return <SecurityView />; return <SecurityView />;
case 'notification': case 'notification':
return <NotificationView />; return <NotificationView />;
case 'about':
return <AppAbout />;
default: default:
break; break;
} }

View File

@ -1,14 +0,0 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"module": "commonjs",
"sourceMap": true,
"jsx": "react"
},
"include": [
"./src/components/YulioID/**/*"
],
"exclude": [
"node_modules"
]
}