This commit is contained in:
srgooglo 2020-03-22 17:29:58 +01:00
parent 911ae7cb21
commit e68b4cc0e8
33 changed files with 370 additions and 485 deletions

3
.env
View File

@ -1 +1,2 @@
UMI_UI=none
UMI_UI=none
NODE_ENV=production

View File

@ -2,6 +2,7 @@
import { resolve } from 'path';
import { i18n } from './config/ycore.config.js';
export default {
ignoreMomentLocale: true,
targets: {
ie: 9,

112
app/main.js Normal file
View File

@ -0,0 +1,112 @@
// Modules to control application life and create native browser window
const path = require('path');
const exec = require('child_process').exec;
const { app, BrowserWindow, ipcMain } = require('electron');
const isDev = process.env.NODE_ENV === 'development';
ipcMain.on('print', async (event, arg) => {
// todo:下载网络文件到本地打印
arg.pdf = `${__dirname}/ReferenceCard.pdf`;
const fileUrl = arg.pdf;
switch (process.platform) {
case 'darwin':
case 'linux':
await exec('lp ' + fileUrl, (e) => {
if (e) throw e;
});
event.reply('asynchronous-reply', 'print done!');
break;
case 'win32':
await exec('print ' + fileUrl, {
windowsHide: true,
}, (e) => {
if (e) throw e;
});
event.reply('asynchronous-reply', 'print done!');
break;
default:
event.reply('asynchronous-reply', 'print failed!');
throw new Error(
'Platform not supported.',
);
}
});
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
const installExtensions = async () => {
const installer = require('electron-devtools-installer');
const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'];
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
for (const name of extensions) {
try {
await installer.default(installer[name], forceDownload);
} catch (e) {
console.log(`Error installing ${name} extension: ${e.message}`);
}
}
};
async function createWindow() {
isDev && await installExtensions();
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1000,
height: 600,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js'),
},
});
// and load the index.html of the app.
if (isDev) {
mainWindow.loadURL('http://localhost:8000/');
// Open the DevTools only if in development mode.
mainWindow.webContents.openDevTools();
} else {
const rdurl = path.join(__dirname, '../dist/index.html') // path.join(__dirname, '../dist/index.html')
console.log(rdurl)
mainWindow.loadFile(rdurl)
}
// Emitted when the window is closed.
mainWindow.on('closed', function() {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
}
// hot reload
isDev && require('electron-reload')(__dirname, {
electron: require(`${__dirname}/../node_modules/electron`),
ignored: /node_modules|[\/\\]\./,
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', function() {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') app.quit();
});
app.on('activate', function() {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) createWindow();
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

8
app/preload.js Normal file
View File

@ -0,0 +1,8 @@
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
for (const versionType of ['chrome', 'electron', 'node']) {
console.log(`${versionType}-version`, process.versions[versionType]);
}
});

3
app/renderer.js Normal file
View File

@ -0,0 +1,3 @@
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.

View File

@ -1,5 +1,19 @@
import {ReturnDevOption} from 'ycore'
export var DevOptions = {
function SettingStoragedValue(e){
try {
const fromStorage = JSON.parse(localStorage.getItem('app_settings'))
const Ite = fromStorage.map(item => {
return item.SettingID === e? item.value : null
})
const fr = Ite.filter(Boolean)
return fr.toString()
}
catch (error) {
return null
}
}
const fromStorage = JSON.parse(localStorage.getItem('app_settings'))
export var AppSettings = {
// Global Behaviors
InfiniteLoading: false,
InfiniteLogin: false,
@ -8,16 +22,14 @@ export var DevOptions = {
DisableRegister: true,
DisablePasswordRecover: true,
// Activating this, the logs must be trowed
ShowFunctionsLogs: ReturnDevOption('force_showDevLogs'),
StrictLightMode: ReturnDevOption('strict_lightMode'),
SignForNotExpire: ReturnDevOption('sessions_noexpire'),
auto_search_ontype: ReturnDevOption('auto_search_ontype'),
auto_feedrefresh: ReturnDevOption('auto_feedrefresh'),
default_showpostcreator: ReturnDevOption('default_showpostcreator'),
default_collapse_sider: ReturnDevOption('default_collapse_sider'),
use_dev_server: ReturnDevOption('use_dev_server'),
force_show_postactions: ReturnDevOption('force_show_postactions'),
MaxJWTexpire: 1556952, //1556952
force_showDevLogs: fromStorage? SettingStoragedValue('force_showDevLogs') : false,
StrictLightMode: fromStorage? SettingStoragedValue('strict_lightMode') : false,
SignForNotExpire: fromStorage? SettingStoragedValue('sessions_noexpire') : false,
auto_search_ontype: fromStorage? SettingStoragedValue('auto_search_ontype') : false,
auto_feedrefresh: fromStorage? SettingStoragedValue('auto_feedrefresh') : false,
default_showpostcreator: fromStorage? SettingStoragedValue('default_showpostcreator') : false,
default_collapse_sider: fromStorage? SettingStoragedValue('default_collapse_sider') : true,
force_show_postactions: fromStorage? SettingStoragedValue('force_show_postactions') : false,
MaxLengthPosts: '512',
CurrentBundle: 'light_ng',
// In KB

View File

@ -10,6 +10,7 @@ module.exports = {
resource_bundle: 'light_ng',
/* Layout configuration, specify which layout to use for route. */
layouts: [
{
@ -23,7 +24,9 @@ module.exports = {
// Global Server Key (Requiered for RS-YIBTP), Not autogenerated, must be included on. (Recommended not modify this constants)
server_key: "f706b0a535b6c2d36545c4137a0a3a26853ea8b5-1223c9ba7923152cae28e5a2e7501b2b-50600768",
},
App_Config: {
InitRes: '800x600',
},
i18n: {
languages: [

View File

@ -1,68 +1,74 @@
const ycore = require('ycore')
const fromStorage = JSON.parse(localStorage.getItem('app_settings'))
export var AppSettings = [
function SettingStoragedValue(e){
try {
const fromStorage = JSON.parse(localStorage.getItem('app_settings'))
const Ite = fromStorage.map(item => {
return item.SettingID === e? item.value : null
})
const fr = Ite.filter(Boolean)
return fr.toString()
}
catch (error) {
return null
}
}
export var ListSettings = [
{
"SettingID": "strict_lightMode",
"type" : "switch",
"title": "Strict Light Mode",
"description": "Force the app to apply full light mode theme when the light mode is activated... (Experimental)",
"value": fromStorage? ycore.StorageValued('strict_lightMode') : false
"value": fromStorage? SettingStoragedValue('strict_lightMode') : false
},
{
"SettingID": "default_collapse_sider",
"type" : "switch",
"title": "Default Collapse Sider",
"description": "Force the app to apply collapsed mode theme when the app is mounted...",
"value": fromStorage? ycore.StorageValued('default_collapse_sider') : true
"value": fromStorage? SettingStoragedValue('default_collapse_sider') : true
},
{
"SettingID": "auto_feedrefresh",
"type" : "switch",
"title": "Auto Feed Refresh",
"description": "Force the app to auto refresh the posts feed when exist news posts for update",
"value": fromStorage? ycore.StorageValued('auto_feedrefresh') : false
"value": fromStorage? SettingStoragedValue('auto_feedrefresh') : false
},
{
"SettingID": "force_showDevLogs",
"type" : "switch",
"title": "Show Functions Logs",
"description": "Show all console logs... [Developer]",
"value": fromStorage? ycore.StorageValued('force_showDevLogs') : false
"value": fromStorage? SettingStoragedValue('force_showDevLogs') : false
},
{
"SettingID": "sessions_noexpire",
"type" : "switch",
"title": "No expire session",
"description": "Force the app to not expire any session... [Developer]",
"value": fromStorage? ycore.StorageValued('sessions_noexpire') : false
"value": fromStorage? SettingStoragedValue('sessions_noexpire') : false
},
{
"SettingID": "auto_search_ontype",
"type" : "switch",
"title": "Auto search",
"description": "Force the app to automaticly search when a type input is detected... [Developer]",
"value": fromStorage? ycore.StorageValued('auto_search_ontype') : false
"value": fromStorage? SettingStoragedValue('auto_search_ontype') : false
},
{
"SettingID": "default_showpostcreator",
"type" : "switch",
"title": "Show default Post Creator",
"description": "Force the app to automaticly search when a type input is detected... [Developer]",
"value": fromStorage? ycore.StorageValued('default_showpostcreator') : false
"value": fromStorage? SettingStoragedValue('default_showpostcreator') : false
},
{
"SettingID": "force_show_postactions",
"type" : "switch",
"title": "Not auto hide Posts Actions",
"description": "Force the app to dont hide the post actions (likes, comments ...etc) automaticly... [Developer]",
"value": fromStorage? ycore.StorageValued('force_show_postactions') : false
},
{
"SettingID": "use_dev_server",
"type" : "switch",
"title": "Use Comty™ Development Server",
"description": "Force the app to connect to an development server... [High Recomended]",
"value": fromStorage? ycore.StorageValued('use_dev_server') : false
"value": fromStorage? SettingStoragedValue('force_show_postactions') : false
},
]

View File

@ -1,40 +0,0 @@
/**
* Query objects that specify keys and values in an array where all values are objects.
* @param {array} array An array where all values are objects, like [{key:1},{key:2}].
* @param {string} key The key of the object that needs to be queried.
* @param {string} value The value of the object that needs to be queried.
* @return {object|undefined} Return frist object when query success.
*/
export function queryArray(array, key, value) {
if (!Array.isArray(array)) {
return
}
return array.filter(_ => _[key] === value)
}
export function randomNumber(min, max) {
return Math.floor(Math.random() * (max - min) + min)
}
export const Constant = {
ApiPrefix: '/api/v1',
NotFound: {
message: 'Not Found',
documentation_url: '',
},
Color: {
green: '#64ea91',
blue: '#8fc9fb',
purple: '#d897eb',
red: '#f69899',
yellow: '#f8c82e',
peach: '#f797d6',
borderBase: '#e5e5e5',
borderSplit: '#f4f4f4',
grass: '#d6fbb5',
sky: '#c1e0fc',
},
}
export Mock from 'mockjs'
export qs from 'qs'

View File

@ -1,30 +0,0 @@
import {
Constant
} from './_utils'
const {
ApiPrefix
} = Constant
const database = [
// DASHBOARD SECTION
{
id: '1',
icon: 'home',
name: 'Main',
route: '/main',
},
{
id: '2',
icon: 'user',
name: 'App Settings',
route: '/settings'
}
]
module.exports = {
[`GET ${ApiPrefix}/routes`](req, res) {
res.status(200).json(database)
},
}

View File

@ -1,73 +1,50 @@
{
"name": "comty-development",
"UUID": "annyudx7eo",
"UUID": "C8mVSr-4nmPp2-pr5Vrz-CU4kg4",
"title": "Comty™",
"DevBuild": true,
"version": "0.2.19",
"version": "0.2.22",
"description": "",
"main": "index.js",
"main": "app/main.js",
"author": "RageStudio",
"license": "ISC",
"build": {
"appId": "com.ragestudio.comtydesktop",
"mac": {
"category": "ragestudio.comty.social.desktop"
}
},
"dependencies": {
"@ant-design/compatible": "^1.0.1",
"@ant-design/pro-layout": "^5.0.0",
"@lingui/react": "^2.9.1",
"@material-ui/core": "^4.9.3",
"@material-ui/icons": "^4.9.1",
"@steveeeie/react-page-transition": "^1.1.2",
"ant-design-pro": "^2.3.2",
"antd": "^4.0.2",
"autoprefixer": "9.7.4",
"axios": "^0.19.2",
"babel-core": "7.0.0-bridge.0",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"classnames": "^2.2.6",
"concurrently": "^5.1.0",
"cryptr": "^6.0.1",
"dotenv": "^8.2.0",
"dva-model-extend": "^0.1.2",
"enquire-js": "^0.2.1",
"immutability-helper": "^3.0.1",
"is-empty": "^1.2.0",
"jquery": "^3.4.1",
"json-format": "^1.0.1",
"jsonwebtoken": "^8.5.1",
"localforage": "^1.7.3",
"lodash": "^4.17.15",
"md5": "^2.2.1",
"moment": "^2.24.0",
"node-sass": "^4.13.1",
"nprogress": "^0.2.0",
"os-utils": "0.0.14",
"passport": "^0.4.1",
"passport-auth0": "^1.3.2",
"passport-jwt": "^4.0.0",
"path-to-regexp": "^6.1.0",
"prop-types": "^15.7.2",
"qs": "^6.9.1",
"radium": "^0.26.0",
"rc-tween-one": "^2.6.8",
"react-animations": "^1.0.0",
"react-dazzle": "^1.4.0",
"react-fullscreen-crossbrowser": "^1.0.9",
"react-helmet": "^5.2.1",
"react-iframe": "^1.8.0",
"react-image": "^2.4.0",
"react-infinite-scroller": "^1.2.4",
"react-modal": "^3.11.1",
"react-new-window": "^0.1.2",
"react-notifications": "^1.4.3",
"react-perfect-scrollbar": "^1.5.8",
"react-responsive": "^8.0.3",
"react-router": "^5.1.2",
"react-scripts": "^3.3.1",
"react-select-country-list": "^2.1.2",
"react-sound": "^1.2.0",
"react-transition-group": "^4.3.0",
"react-virtualized": "^9.21.2",
"recompose": "^0.30.0",
"sqlite": "^3.0.3",
"store": "^2.0.12",
"ts-cookies": "^1.0.0",
"umi-plugin-datahub": "^4.1.0",
@ -84,6 +61,10 @@
"babel-plugin-macros": "^2.8.0",
"babel-plugin-module-resolver": "^4.0.0",
"cross-env": "^7.0.0",
"electron": "^8.1.1",
"electron-builder": "^22.4.1",
"electron-devtools-installer": "^2.2.4",
"electron-reload": "^1.5.0",
"eslint": "^6.8.0",
"eslint-config-react-app": "^5.2.0",
"eslint-plugin-flowtype": "^4.6.0",
@ -93,7 +74,6 @@
"husky": "^4.2.3",
"less-vars-to-js": "^1.3.0",
"lint-staged": "^10.0.7",
"mockjs": "^1.1.0",
"module": "^1.2.5",
"now": "^17.0.3",
"prettier": "^1.19.1",
@ -125,9 +105,18 @@
}
},
"scripts": {
"day": "umi dev && grunt bump minor",
"app-dev": "umi dev && grunt bump",
"tsc:w": "tsc -w",
"clean": "rimraf dist",
"postinstall": "electron-builder install-app-deps",
"app-dev": "concurrently \"npm run start\" \"wait-on http://localhost:8000 && npm run electron-dev\"",
"electron-dev": "cross-env NODE_ENV=development electron .",
"electron-prod": "cross-env NODE_ENV=production electron .",
"pack:mac": "npm run clean && npm run build && npm run private:build:mac",
"pack:win": "npm run clean && npm run build && npm run private:build:win",
"pack:linux": "npm run clean && npm run build && npm run private:build:linux",
"private:build:all": "electron-builder -mwl",
"private:build:mac": "electron-builder --mac",
"private:build:win": "electron-builder -c.extraMetadata.main=public/electron.js --win --x64",
"private:build:linux": "electron-builder --linux",
"analyze": "cross-env ANALYZE=1 umi build",
"build": "umi build",
"start": "umi dev",

8
public/preload.js Normal file
View File

@ -0,0 +1,8 @@
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
for (const versionType of ['chrome', 'electron', 'node']) {
console.log(`${versionType}-version`, process.versions[versionType]);
}
});

3
public/renderer.js Normal file
View File

@ -0,0 +1,3 @@
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.

View File

@ -1,8 +1,40 @@
import * as ycore from 'ycore'
var jquery = require("jquery");
import * as Icons from '@ant-design/icons'
import { RenderFeed } from 'components/MainFeed'
export const FeedHandler = {
refresh: () => {
RenderFeed.RefreshFeed()
},
killByID: (post_id) => {
RenderFeed.killByID(post_id)
},
addToRend: (payload) => {
RenderFeed.addToRend(payload)
}
}
export const IsThisPost = {
owner: (post_uid) => {
const a = ycore.handlerYIDT.__id()
if (post_uid == a) {
return true
}
return false
},
boosted: () => {
},
pinned: () => {
},
flagged: () => {
}
}
export function GetGeneralData(callback){
let formdata = new FormData();
formdata.append("user_id", id);
@ -252,7 +284,7 @@ export function GetPosts(userid, type, fkey, callback) {
let formdata = new FormData();
formdata.append("server_key", ycore.yConfig.server_key);
formdata.append("after_post_id", (fkey || 0))
formdata.append("limit", ycore.DevOptions.limit_post_catch || 20)
formdata.append("limit", ycore.AppSettings.limit_post_catch || 20)
switch (type) {
case 'feed':
formdata.append("type", "get_news_feed");

View File

@ -1,8 +1,8 @@
import {DevOptions} from 'ycore'
import {AppSettings} from 'ycore'
export function CurrentTheme(){
try {
const bundle = localStorage.getItem('resource_bundle') || DevOptions.resource_bundle
const bundle = localStorage.getItem('resource_bundle') || AppSettings.resource_bundle
console.log('Loading resource Bundle =>', bundle)
return bundle
} catch (error) {

View File

@ -27,10 +27,10 @@ function __API__User (payload, sdcp){
dev,
is_pro,
username,
exp: ycore.DevOptions.SignForNotExpire? 0 : Math.floor(Date.now() / 1000) + (60 * 60),
exp: ycore.AppSettings.SignForNotExpire? 0 : Math.floor(Date.now() / 1000) + (60 * 60),
}
ycore.handlerYIDT.set(frame, done => {
done? ycore.RefreshONCE() : null
done? ycore.crouter.native('main') : null
})
}
@ -82,7 +82,7 @@ export function ValidLoginSession(callback){
let validtoken = false;
const a = Cookies.get('cid');
if (a) {
const modExp = ycore.DevOptions.SignForNotExpire;
const modExp = ycore.AppSettings.SignForNotExpire;
const ad = jwt.decode(a)
let notexp = true; // Sets if this is expired (Default is not expired)

View File

@ -5,7 +5,7 @@
* @licensed Pending...
*/
import {AppSettings} from "../../globals/settings.js";
import {ListSettings} from "../../globals/settings.js";
import {Endpoints} from "globals/endpoints.js";
import * as Icons from '@ant-design/icons';
import localforage from "localforage"
@ -99,7 +99,7 @@ export const AppInfo = {
* @param e {String} String of SettingID for search
* @return {string} Boolean value
*/
export function StorageValued(e){
export function SettingStoragedValue(e){
try {
const fromStorage = JSON.parse(localStorage.getItem('app_settings'))
const Ite = fromStorage.map(item => {
@ -113,20 +113,6 @@ export function StorageValued(e){
}
}
/**
* Return the values as alias (AppSettings, DevOptions)
*
* @param e {String} String of SettingID for search
* @return {string} Boolean value
*/
export function ReturnDevOption(e){
const Ite = AppSettings.map(item => {
return item.SettingID === e? item.value : null
})
const fr = Ite.filter(Boolean)
return fr.toString()
}
/**
* Global fix for convert '1, 0' to string boolean 'true, false'
*
@ -202,7 +188,7 @@ export function requestFullscreen(){
*
*/
export function RefreshONCE(){
window.location.reload();
window.location = "/"
}
/**
* Parse information about this App
@ -236,6 +222,7 @@ export function DetectNoNStableBuild(e1) {
break;
}
}
/**
* User console with setting user permissions
*
@ -243,19 +230,19 @@ export function DetectNoNStableBuild(e1) {
*/
export const yconsole = {
log: (...cont)=>{
ReturnDevOption('force_showDevLogs')? console.log(...cont) : null
SettingStoragedValue('force_showDevLogs')? console.log(...cont) : null
return
},
debug: (...cont)=>{
ReturnDevOption('force_showDevLogs')? console.debug(...cont) : null
SettingStoragedValue('force_showDevLogs')? console.debug(...cont) : null
return
},
error: (...cont)=>{
ReturnDevOption('force_showDevLogs')? console.error(...cont) : null
SettingStoragedValue('force_showDevLogs')? console.error(...cont) : null
return
},
warn: (...cont)=>{
ReturnDevOption('force_showDevLogs')? console.warn(...cont) : null
SettingStoragedValue('force_showDevLogs')? console.warn(...cont) : null
return
}
}

View File

@ -39,7 +39,7 @@ export default class HeaderSearch extends Component {
onChange = e => {
const { value } = e.target;
this.setState({value: value})
if (ycore.DevOptions.auto_search_ontype == 'true') {
if (ycore.AppSettings.auto_search_ontype == 'true') {
this.autosend()
}
};

View File

@ -1,102 +0,0 @@
import React from 'react'
import * as antd from 'antd'
import styles from './post.less'
import {CustomIcons, LikeBTN} from 'components'
import * as ycore from 'ycore'
import * as Icons from '@ant-design/icons';
const { Meta } = antd.Card;
// Set default by configuration
const emptyPayload = {user: 'Post Empty', ago: 'This Post is empty', avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png', content: 'Test Test' }
export default class SecondaryPostCard extends React.Component{
constructor(props){
super(props),
this.state = {
FadeIN: true
}
}
renderPostPlayer(payload){
const ident = payload
if (ident.includes('.mp4')) {
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} />
)
}
}
render(){
const { payload, customActions } = this.props
const ActShowMode = ycore.DevOptions.force_show_postactions
const { id, post_time, postText, postFile, get_post_comments, 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>,
<MICON.InsertComment key="comments" onClick={ ()=> ycore.crouter.native(`p/${id}`) } />
]
const actions = customActions || defaultActions;
const MoreMenu = (
<antd.Menu>
<antd.Menu.Item key="0">
key 0
</antd.Menu.Item>
</antd.Menu>
);
return(
<div className={styles.cardWrapper}>
<antd.Card hoverable className={ActShowMode? styles.showMode : null} actions={actions} >
<Meta
avatar={<div className={styles.postAvatar}><antd.Avatar shape="square" size={50} src={publisher.avatar} /></div>}
title={
<div className={styles.titleWrapper} >
<h4 onClick={() => ycore.crouter.native(`@${publisher.username}`)} className={styles.titleUser}>@{publisher.username} {ycore.booleanFix(publisher.verified)? <Icon style={{ color: 'blue' }} component={CustomIcons.VerifiedBadge} /> : null}{ycore.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 overlay={MoreMenu} trigger={['click']}><Icons.MoreOutlined key="actionMenu" /></antd.Dropdown></div>
{ycore.booleanFix(is_post_pinned)? (<Icons.PushpinFilled /> ): null }
</div>
</div>}
description={<span className={styles.textAgo}>{post_time}</span>}
bordered="false"
/>
{postText? <div className={styles.postContent}> <h3 dangerouslySetInnerHTML={{__html: postText }} /> </div> : null}
{postFile? <div className={styles.postContentFILE}>{this.renderPostPlayer(postFile)}</div> : null }
<div className={styles.ellipsisIcon}><Icons.EllipsisOutlined /></div>
</antd.Card>
</div>
)
}
}

View File

@ -1,176 +0,0 @@
@import '~themes/vars.less';
.cardWrapper{
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
border-radius: 7px;
max-width: 510px;
min-width: 265px;
width: auto;
margin: 23px auto 50px auto;
:global{
.ant-card-meta-detail > div:not(:last-child){
margin: 0
}
.ant-card {
border-radius: 7px;
border: 0;
border-top: 1px solid #4646460c;
}
.ant-card-body {
padding: 13px 0 5px 0;
}
.ant-card-actions {
border-top: 0;
background: #EBEBEB;
height: 30px;
position: relative;
transition: opacity 150ms linear, position 150ms linear, transform 150ms linear;
border-radius: 0 0 10px 10px;
opacity: 0;
// Doesn't work... So sad :C
&.showMode{
opacity: 1;
transform: translate(0, 15px);
}
}
.ant-card-actions:hover {
opacity: 1;
transform: translate(0, 15px);
transition: opacity 150ms linear, position 150ms linear, transform 150ms linear;
}
.ant-card-actions > li > span > .anticon {
font-size: 16px;
line-height: 22px;
width: 40px;
height: 40px;
background: white;
border-radius: 23px;
}
.ant-card-actions > li {
margin: -20px 0 0 0 ;
border-right: 0;
span {
font-size: 16px;
line-height: 22px;
width: 40px;
height: 40px;
background: white;
border-radius: 23px;
margin: auto;
}
svg {
height: 20px;
width: 20px;
height: 100%;
vertical-align: middle;
}
}
}
}
.showMode{
:global{
ul {
opacity: 1 !important;
transform: translate(0, 15px);
}
}
}
.postAvatar{
position: absolute;
left: -8px;
top: -8px;
display: flex;
}
.titleUser{
display: flex;
font-family: 'Poppins', sans-serif;
margin: 0 0 0 50px;
}
.textAgo{
display: flex;
font-size: 10px;
margin: 0 0 0 53px;
}
.PostTags{
float: right;
width: 100%;
z-index: 10;
:global {
.anticon{
color:rgb(249, 179, 64);
float: right;
margin: -0 6px 0 0;;
font-size: 17px;
}
.MoreMenu{
color: #2d2d2d !important;
}
}
}
.titleWrapper{
display: flex;
h4{
cursor: pointer;
}
}
.postContent{
word-break: break-all;
display: flex;
border-radius: 3px;
margin: 23px 24px 23px 24px;
h3{
font-family: "Poppins", sans-serif;
color: #555555;
font-weight: 400;
font-size: 15px;
letter-spacing: -0.3px;
}
}
.postContentFILE{
display: flex;
margin: 23px 0 5px 0;
max-height: 600px;
overflow: hidden;
img {
width: calc(100% + 30px);
overflow: hidden;
margin: auto;
}
video {
max-height: 600px;
width: calc(100% + 30px);
overflow: hidden;
}
h3{
color: rgb(85, 85, 85);
font-weight: 470;
}
}
.likebtn{
:global{
svg{
color:rgba(0, 0, 0, 0.45);
}
svg:hover{
color: rgb(233, 35, 68);
transition: all 0.2s linear;
}
}
}
.ellipsisIcon{
color:rgba(0, 0, 0, 0.45);
width: 100%;
position: absolute;
text-align: center;
margin: auto;
font-size: 30px;
transition: opacity 150ms linear;
}
.ellipsisIcon:hover{
opacity: 0;
transition: opacity 150ms linear;
}

View File

@ -27,7 +27,7 @@ class Sider extends PureComponent {
StrictMode = () =>{
const { theme } = this.props;
if (ycore.DevOptions.StrictLightMode == false) {
if (ycore.AppSettings.StrictLightMode == false) {
return "dark"
}
return theme

View File

@ -1,12 +1,12 @@
import React from 'react'
import {CoreLoader} from 'components'
import { DevOptions } from 'ycore'
import { AppSettings } from 'ycore'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import styles from './Loader.less'
const Loader = ({ spinning = true, fullScreen }) => {
if (DevOptions.InfiniteLoading == true) {
if (AppSettings.InfiniteLoading == true) {
return (
<div className={styles.loader}>
<div className={styles.warpper}>

View File

@ -5,10 +5,19 @@ import * as Icons from '@ant-design/icons'
import {PostCard} from 'components'
export function RefreshFeed(){
ycore.yconsole.log('Refreshing Feed...')
window.MainFeedComponent.FirstGet();
return
export const RenderFeed = {
RefreshFeed: () => {
window.MainFeedComponent.FirstGet();
return
},
killByID: (post_id) => {
window.MainFeedComponent.killByID(post_id);
return
},
addToRend: (payload) => {
window.MainFeedComponent.addToRend(payload);
return
}
}
class MainFeed extends React.Component {
constructor(props){
@ -29,10 +38,22 @@ class MainFeed extends React.Component {
toogleLoader(){
this.setState({ loading: !this.state.loading })
}
killByID(post_id){
}
addToRend(payload){
console.log(payload)
}
FirstGet() {
try{
const { get, uid, filters } = this.props;
if (this.props.custompayload) {
this.setState({ isEnd: true, data: this.props.custompayload, loading: false })
return
}
if (!get) {
ycore.yconsole.error('Please, fill params with an catch type...')
return
@ -49,7 +70,7 @@ class MainFeed extends React.Component {
}
const parsed = JSON.parse(result)['data']
const isEnd = parsed.length < ycore.DevOptions.limit_post_catch? true : false
const isEnd = parsed.length < ycore.AppSettings.limit_post_catch? true : false
this.setState({ isEnd: isEnd, data: parsed, loading: false })
})
}catch(err){
@ -76,7 +97,7 @@ class MainFeed extends React.Component {
const oldData = this.state.data
const parsed = JSON.parse(res)['data']
const mix = oldData.concat(parsed)
const isEnd = parsed.length < ycore.DevOptions.limit_post_catch? true : false
const isEnd = parsed.length < ycore.AppSettings.limit_post_catch? true : false
this.setState({ isEnd: isEnd, data: mix, loading: false }, () => ycore.gotoElement(getLastPost.id) )
return true
})
@ -88,6 +109,7 @@ class MainFeed extends React.Component {
renderFeedPosts = () =>{
const {data, loading, isEnd} = this.state
const loadMore =
!isEnd && !loading ? (
<div style={{

View File

@ -8,6 +8,7 @@ import Icon from '@ant-design/icons'
import classnames from 'classnames'
import * as MICON from '@material-ui/icons';
const { Meta } = antd.Card;
// Set default by configuration
@ -68,20 +69,44 @@ class PostCard extends React.PureComponent{
render(){
const { payload, customActions } = this.props
const ActShowMode = ycore.DevOptions.force_show_postactions
const ActShowMode = ycore.AppSettings.force_show_postactions
const { id, post_time, postText, postFile, get_post_comments, postFileName, publisher, post_likes, is_post_pinned, is_liked } = payload || emptyPayload;
const handlePostActions = {
delete: (post_id) => {
ycore.ActionPost('delete', post_id, null, (err, res)=>{
if (err) {
return false
}
ycore.yconsole.log(res)
ycore.FeedHandler.killByID(post_id)
})
},
save: () => {
}
}
const defaultActions = [
<div><LikeBTN count={post_likes} id={id} liked={ycore.booleanFix(is_liked)? true : false} key="like" /></div>,
<MICON.InsertComment key="comments" onClick={ ()=> this.goToPost(id) } />
]
const actions = customActions || defaultActions;
const MoreMenu = (
<antd.Menu>
<antd.Menu.Item key="0">
key 0
</antd.Menu.Item>
{ycore.IsThisPost.owner(publisher.id)?
<antd.Menu.Item onClick={ ()=> handlePostActions.delete(id) } key="remove_post">
<Icons.DeleteOutlined /> Remove post
</antd.Menu.Item>
: null
}
<antd.Menu.Item pid={id} key="save_post">
<Icons.SaveOutlined /> Save post
</antd.Menu.Item>
<antd.Menu.Item pid={id} key="test">
<Icons.SaveOutlined /> Test CRAZY GAI
</antd.Menu.Item>
</antd.Menu>
);

View File

@ -2,7 +2,6 @@ import React from 'react'
import * as antd from 'antd'
import * as ycore from 'ycore'
import styles from './index.less'
import { RefreshFeed } from 'components/MainFeed'
import * as Icons from '@ant-design/icons';
import Icon from '@ant-design/icons'
import * as MICONS from '@material-ui/icons'
@ -28,7 +27,7 @@ class PostCreator extends React.PureComponent{
this.state = {
visible: true,
FadeIN: true,
keys_remaining: ycore.DevOptions.MaxLengthPosts,
keys_remaining: ycore.AppSettings.MaxLengthPosts,
rawtext: '',
posting: false,
posting_ok: false,
@ -103,20 +102,20 @@ class PostCreator extends React.PureComponent{
if (!filter) {
antd.message.error(`${file.type} This file is not valid!`);
}
const maxsize = file.size / 1024 / 1024 < ycore.DevOptions.MaximunAPIPayload;
const maxsize = file.size / 1024 / 1024 < ycore.AppSettings.MaximunAPIPayload;
if (!maxsize) {
antd.message.error(`Image must smaller than ${ycore.DevOptions.MaximunAPIPayload} KB!`);
antd.message.error(`Image must smaller than ${ycore.AppSettings.MaximunAPIPayload} KB!`);
}
return filter && maxsize;
}
handleChanges = ({ target: { value } }) => {
this.setState({ rawtext: value, keys_remaining: (ycore.DevOptions.MaxLengthPosts - value.length) })
this.setState({ rawtext: value, keys_remaining: (ycore.AppSettings.MaxLengthPosts - value.length) })
}
handleKeysProgressBar(){
const { keys_remaining } = this.state;
if (keys_remaining <= (ycore.DevOptions.MaxLengthPosts/100*30)) {
if (keys_remaining <= (ycore.AppSettings.MaxLengthPosts/100*30)) {
return 'exception'
}else return('active')
}
@ -134,7 +133,7 @@ class PostCreator extends React.PureComponent{
file: ''
})
setTimeout( () => {this.setState({ posting_ok: false }) }, 1000)
RefreshFeed()
ycore.FeedHandler.refresh()
return true
}
@ -143,7 +142,7 @@ class PostCreator extends React.PureComponent{
if(!rawtext){
return null
}
this.setState({ posting: true, keys_remaining: ycore.DevOptions.MaxLengthPosts })
this.setState({ posting: true, keys_remaining: ycore.AppSettings.MaxLengthPosts })
ycore.PublishPost(ycore.GetPostPrivacy.bool(shareWith), rawtext, file, (err, res) => {
if (err) {
ycore.notifyError(err)
@ -186,7 +185,7 @@ class PostCreator extends React.PureComponent{
canPost(){
const { fileURL, keys_remaining, } = this.state
const isTypedSomething = (keys_remaining < ycore.DevOptions.MaxLengthPosts)
const isTypedSomething = (keys_remaining < ycore.AppSettings.MaxLengthPosts)
const isUploadedFile = (fileURL? true : false)
return isUploadedFile || isTypedSomething
@ -195,7 +194,7 @@ class PostCreator extends React.PureComponent{
render(){
const {userData} = this.props
const { keys_remaining, visible, fileURL, file } = this.state;
const percent = (((keys_remaining/ycore.DevOptions.MaxLengthPosts) * 100).toFixed(2) )
const percent = (((keys_remaining/ycore.AppSettings.MaxLengthPosts) * 100).toFixed(2) )
const changeShare = ({ key }) => {
this.setState({ shareWith: key })
}
@ -229,7 +228,7 @@ class PostCreator extends React.PureComponent{
</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={8} />
<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.AppSettings.MaxLengthPosts} rows={8} />
<div><antd.Button disabled={this.state.posting? true : !this.canPost() } onClick={this.handlePublishPost} type="primary" icon={this.state.posting_ok? <Icons.CheckCircleOutlined/> : (this.state.posting? <Icons.LoadingOutlined /> : <Icons.ExportOutlined /> )} /></div>
</> }

View File

@ -3,7 +3,7 @@ import styles from './styles.less'
import * as ycore from 'ycore'
import * as antd from 'antd'
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import {CustomIcons, MainFeed} from 'components'
import {CustomIcons, MainFeed, PostCreator} from 'components'
import { SetHeaderSearchType } from 'components/HeaderSearch'
import * as Icons from '@ant-design/icons';
import Icon from '@ant-design/icons'
@ -111,6 +111,7 @@ class UserProfile extends React.Component {
{loading? <antd.Skeleton active /> :
(<div>
{invalid? null: this.UserHeader(this.state.RenderValue)}
<PostCreator userData={ycore.userData()} />
<MainFeed get='user' uid={UUID} />
</div>)
}

View File

@ -49,7 +49,7 @@ class YulioID extends Component {
if (EncUsername && EncPassword){
this.setState({ ShowLoading: true, StateMessage: 'Wait a sec...' });
if (ycore.DevOptions.InfiniteLogin == true) {
if (ycore.AppSettings.InfiniteLogin == true) {
ycore.yconsole.log(prefix, 'InfiniteLogin is enabled! Disabled getAuth')
}
else {

View File

@ -25,7 +25,7 @@ class PrimaryLayout extends React.Component {
super(props)
window.PrimaryComponent = this;
this.state = {
collapsed: (ycore.DevOptions.default_collapse_sider? true : false),
collapsed: (ycore.AppSettings.default_collapse_sider? true : false),
isMobile: false,
userData: ''
}

View File

@ -44,13 +44,11 @@ export default {
},
},
effects: {
*query({payload}, { call, put, select }) {
*query({payload}, { call, put, select }) {
const validBackup = ycore.ValidBackup();
if ( ycore.ValidLoginSession() == true) {
if (pathMatchRegexp(['/', '/login'], window.location.pathname)) {
router.push({pathname: '/main',})
ycore.RefreshONCE()
}
ycore.MakeBackup()
ycore.UpdateSDCP()
@ -60,9 +58,8 @@ export default {
if (validBackup == true) {
ycore.LogoutCall()
}
else{
else{
router.push({pathname: '/login',})
ycore.RefreshONCE()
}
}
if(pathMatchRegexp([''], window.location.pathname)){

View File

@ -6,6 +6,7 @@ import * as Icons from '@ant-design/icons';
import jwt from 'jsonwebtoken'
import styles from './style.less'
import MainFeed from '../../components/MainFeed';
const UserData = ycore.userData()
@ -57,6 +58,9 @@ export default class __m extends React.Component {
const arrayOfSDCP = Object.entries(UserData).map((e) => ( { [e[0]]: e[1] } ));
const { UserID, UserToken, expiresIn } = this.state.s_token
const { ValidSDCP, ValidCookiesToken, final } = this.state.s_ses
const AddDummy = {id: `${Math.random()}`, publisher: {id: "1"},post_id: "1", user_id: "48", recipient_id: "0", postText: "Dummy Payload"}
return (
<div className={styles.Wrapper}>
<div className={styles.titleHeader}>
@ -96,7 +100,7 @@ export default class __m extends React.Component {
<antd.Button onClick={() => ycore.notifyError(`
ycore.GetPosts(uid, get, '0', (err, result) => {
const parsed = JSON.parse(result)['data']
const isEnd = parsed.length < ycore.DevOptions.limit_post_catch? true : false
const isEnd = parsed.length < ycore.AppSettings.limit_post_catch? true : false
this.setState({ isEnd: isEnd, data: parsed, loading: false })
})`
)} > Send mock notifyError() </antd.Button>
@ -118,6 +122,21 @@ export default class __m extends React.Component {
</antd.Card>
</div>
<div className={styles.titleHeader}>
<h1><Icons.BugOutlined /> MainFeed | ENV Test</h1>
</div>
<div className={styles.sectionWrapper}>
<antd.Card>
<antd.Button onClick={() => ycore.FeedHandler.addToRend(AddDummy)}> ADD DUMMY </antd.Button>
<antd.Button> KillByID </antd.Button>
<hr />
<MainFeed custompayload={[{id: "1", publisher: {id: "1"},post_id: "1", user_id: "48", recipient_id: "0", postText: "Dummy Payload"}, {id: "2", post_id: "2", publisher: {id: "1"}, user_id: "48", recipient_id: "0", postText: "Dummy Payload"}]} />
</antd.Card>
</div>

View File

@ -1,12 +1,10 @@
import React, { PureComponent } from 'react'
import Redirect from 'umi/redirect'
import { withI18n } from '@lingui/react'
import * as ycore from 'ycore'
@withI18n()
class Index extends PureComponent {
render() {
const { i18n } = this.props
return <Redirect to={i18n.t`/dashboard`} />
ycore.crouter.native(`login`)
}
}

View File

@ -1,7 +1,7 @@
import React, { Component, Fragment } from 'react';
import { List, Switch, Button, notification, InputNumber } from 'antd';
import { AppSettings } from '../../../../globals/settings.js'
import { DevOptions, ControlBar } from 'ycore'
import { ListSettings } from '../../../../globals/settings.js'
import { ControlBar } from 'ycore'
import * as ycore from "ycore"
import * as Icons from '@ant-design/icons'
import Icon from '@ant-design/icons'
@ -11,7 +11,7 @@ class Base extends Component {
constructor(props){
super(props),
this.state = {
SettingRepo: AppSettings,
SettingRepo: ListSettings,
forSave: false
}
}

7
webpack.config.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = {
resolve: {
alias: {
'@': require('path').resolve(__dirname, 'src'),
},
},
};