mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 10:34:17 +00:00
update: customization, optimization, core
This commit is contained in:
parent
7b48c13c43
commit
6923ce90c9
@ -3,7 +3,10 @@ import { resolve } from 'path'
|
||||
import { i18n } from './config/ycore.config.js'
|
||||
export default {
|
||||
ignoreMomentLocale: true,
|
||||
hash: true,
|
||||
hash: false,
|
||||
|
||||
ssr: false,
|
||||
|
||||
targets: { ie: 9,},
|
||||
treeShaking: true,
|
||||
plugins: [
|
||||
@ -65,6 +68,7 @@ export default {
|
||||
// Webpack Configuration
|
||||
alias: {
|
||||
app: resolve(__dirname, './src/@app/app.js'),
|
||||
keys: resolve(__dirname, './config/keys.js'),
|
||||
globals: resolve(__dirname, './globals'),
|
||||
components: resolve(__dirname, './src/components'),
|
||||
config: resolve(__dirname, './config/ycore.config.js'),
|
||||
|
@ -1,6 +1,8 @@
|
||||
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',
|
||||
unsplash_key: "slrHmuo9FEJajV4xvWl38TUhbib6BhhGI4VIZ1-cqnw",
|
||||
unsplash_secret: "dh3UlgLTdunO7a_l_iKjotXbz0xB7w5EuDIBU8Pa8pA",
|
||||
g_recaptcha_key: '6Lc55uUUAAAAAEIACMVf3BUzAJSNCmI3RrjEirZ6',
|
||||
g_recaptcha_secret: '6Lc55uUUAAAAAOP4OgUa5DpqJC-70t53AmW0lyYf',
|
||||
// Global Server Key (Requiered for RS-YIBTP), Not autogenerated, must be included on. (Recommended not modify this constant)
|
||||
server_key: 'f706b0a535b6c2d36545c4137a0a3a26853ea8b5-1223c9ba7923152cae28e5a2e7501b2b-50600768',
|
||||
}
|
||||
|
@ -3,6 +3,5 @@ const path = require('path')
|
||||
const lessToJs = require('less-vars-to-js')
|
||||
|
||||
module.exports = () => {
|
||||
const themePath = path.join(__dirname, `../src/themes/index.less`)
|
||||
return lessToJs(fs.readFileSync(themePath, 'utf8'))
|
||||
// return {"@__Global_backgroud_image": "url(https://images.unsplash.com/photo-1471286274405-579f8d7132d8?.jpg)"}
|
||||
}
|
||||
|
@ -8,19 +8,21 @@ module.exports = {
|
||||
DarkLogoPath: '/dark_logo.svg',
|
||||
|
||||
resource_bundle: 'light_ng',
|
||||
sync_server: 'http://localhost:5500',
|
||||
server_endpoint: 'https://comty.pw',
|
||||
|
||||
g_recaptcha_key: '6Lc55uUUAAAAAEIACMVf3BUzAJSNCmI3RrjEirZ6',
|
||||
g_recaptcha_secret: '6Lc55uUUAAAAAOP4OgUa5DpqJC-70t53AmW0lyYf',
|
||||
sync_server: 'http://85.251.59.39:6050',
|
||||
rest_server: 'https://comty.pw',
|
||||
|
||||
/* Layout configuration, specify which layout to use for route. */
|
||||
layouts: [
|
||||
{
|
||||
name: 'primary',
|
||||
include: [/.*/],
|
||||
exclude: [/\/login/, /\/socket\/(.*)/, /\/publics/, /\/authorize/],
|
||||
include: [/\/main/, /\/settings/, /\/saves/, /\/pro/, /\/chats/, /\//],
|
||||
exclude: [/\/publics/, /\/login/ ],
|
||||
},
|
||||
{
|
||||
name: 'public',
|
||||
include: [/.*/]
|
||||
}
|
||||
],
|
||||
|
||||
i18n: {
|
||||
|
@ -1,13 +1,12 @@
|
||||
import * as Icons from '@ant-design/icons'
|
||||
|
||||
|
||||
export var BadgesType = [
|
||||
{
|
||||
id: 'alpha_test',
|
||||
title: 'Alpha Tester',
|
||||
color: 'green',
|
||||
require: '',
|
||||
icon: (<Icons.BugOutlined />),
|
||||
icon: (<Icons.BugOutlined />),
|
||||
tip: 'Oh yeah!'
|
||||
},
|
||||
{
|
||||
@ -41,5 +40,13 @@ export var BadgesType = [
|
||||
require: '',
|
||||
icon: (<Icons.SmileOutlined />),
|
||||
tip: 'hump....',
|
||||
},
|
||||
{
|
||||
id: 'el_walter_pro',
|
||||
title: 'Pro Chikito',
|
||||
color: '#a0d911',
|
||||
require: '',
|
||||
icon: (<Icons.AndroidOutlined />),
|
||||
tip: 'Chikito',
|
||||
}
|
||||
]
|
||||
|
@ -1,2 +1,3 @@
|
||||
export * from './comty_endpoints.js'
|
||||
export * from './twitter_endpoints.js'
|
||||
export * from './twitter_endpoints.js'
|
||||
export * from './unsplash_endpoints.js'
|
5
globals/endpoints/spotify_endpoints.js
Normal file
5
globals/endpoints/spotify_endpoints.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
autorize: 'https://accounts.spotify.com/authorize',
|
||||
}
|
||||
|
||||
|
6
globals/endpoints/unsplash_endpoints.js
Normal file
6
globals/endpoints/unsplash_endpoints.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
unsplash_endpoints: {
|
||||
api: "https://api.unsplash.com/",
|
||||
search: "https://api.unsplash.com/search/photos"
|
||||
}
|
||||
}
|
6
globals/links.js
Normal file
6
globals/links.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
gitlab: "https://gitlab.com/rstudio-development/comty-development",
|
||||
github:"https://github.com/srgooglo/Comty-Development",
|
||||
trellojoin: "https://trello.com/invite/b/UbwvlG1I/2bc02725b9b210d2e9e9a82c5040b895/comty-development",
|
||||
patreon: "https://www.patreon.com/rstudio",
|
||||
}
|
44
globals/sidebar_menu.js
Normal file
44
globals/sidebar_menu.js
Normal file
@ -0,0 +1,44 @@
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
import {CustomIcons} from 'components'
|
||||
import * as Feather from 'feather-reactjs'
|
||||
|
||||
let MenuList = [
|
||||
{
|
||||
id: 'main',
|
||||
title: 'Main',
|
||||
path: '/main',
|
||||
require: 'login',
|
||||
icon: <Feather.Home />,
|
||||
},
|
||||
{
|
||||
id: 'explore',
|
||||
title: 'Explore',
|
||||
path: '/explore',
|
||||
require: 'login',
|
||||
icon: <Feather.Compass />,
|
||||
},
|
||||
{
|
||||
id: 'saves',
|
||||
title: 'Saves',
|
||||
path: '/saves',
|
||||
require: 'login',
|
||||
icon: <Feather.Bookmark />,
|
||||
},
|
||||
{
|
||||
id: 'messages',
|
||||
title: 'Messages',
|
||||
path: '/messages',
|
||||
require: 'login',
|
||||
icon: <Feather.MessageSquare />,
|
||||
},
|
||||
{
|
||||
id: 'notifications',
|
||||
title: 'Notifications',
|
||||
path: '/notifications',
|
||||
require: 'login',
|
||||
icon: <Feather.Inbox/>,
|
||||
},
|
||||
]
|
||||
|
||||
export default MenuList
|
@ -2,8 +2,7 @@
|
||||
"name": "Comty",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "white",
|
||||
"description": "RageStudio users dashboard",
|
||||
"description": "An client prototype of universal social network.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "logo.svg"
|
||||
|
18
package.json
18
package.json
@ -3,7 +3,7 @@
|
||||
"UUID": "C8mVSr-4nmPp2-pr5Vrz-CU4kg4",
|
||||
"title": "Comty™",
|
||||
"DevBuild": true,
|
||||
"version": "0.4.06",
|
||||
"version": "0.4.11",
|
||||
"stage": "dev-pre",
|
||||
"description": "",
|
||||
"author": "RageStudio",
|
||||
@ -15,27 +15,35 @@
|
||||
"@material-ui/core": "^4.9.9",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"antd": "^4.1.2",
|
||||
"axios": "^0.19.2",
|
||||
"canvas": "^2.6.1",
|
||||
"classnames": "^2.2.6",
|
||||
"colorthief": "^2.3.0",
|
||||
"dva": "2.4.1",
|
||||
"dva-model-extend": "^0.1.2",
|
||||
"enquire-js": "^0.2.1",
|
||||
"express": "^4.17.1",
|
||||
"feather-reactjs": "^2.0.9",
|
||||
"feather-reactjs": "^2.0.13",
|
||||
"interactjs": "^1.9.9",
|
||||
"jquery": "^3.4.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"koa": "^2.7.0",
|
||||
"koa-compress": "^3.0.0",
|
||||
"koa-mount": "^4.0.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"localforage": "^1.7.3",
|
||||
"lodash": "^4.17.15",
|
||||
"md5": "^2.2.1",
|
||||
"moment": "^2.24.0",
|
||||
"node-sass": "^4.13.1",
|
||||
"nodemon": "^1.19.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.1.0",
|
||||
"peerjs": "^1.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"puppeteer": "^3.0.3",
|
||||
"radium": "^0.26.0",
|
||||
"randomstring": "^1.1.5",
|
||||
"react-animations": "^1.0.0",
|
||||
"react-color": "^2.18.1",
|
||||
"react-dazzle": "^1.4.0",
|
||||
"react-emoji": "^0.5.0",
|
||||
"react-feather": "^2.0.8",
|
||||
@ -53,6 +61,8 @@
|
||||
"ts-cookies": "^1.0.0",
|
||||
"umi": "^2.13.12",
|
||||
"umi-plugin-react": "^1.15.7",
|
||||
"umi-request": "^1.2.4",
|
||||
"umi-server": "^1.2.3",
|
||||
"validator": "^12.2.0",
|
||||
"ycorejs": "^0.1.1"
|
||||
},
|
||||
|
51
server.js
Normal file
51
server.js
Normal file
@ -0,0 +1,51 @@
|
||||
require('regenerator-runtime/runtime');
|
||||
const server = require('umi-server');
|
||||
const Koa = require('koa');
|
||||
const compress = require('koa-compress');
|
||||
const mount = require('koa-mount');
|
||||
const { join, extname } = require('path');
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
const root = join(__dirname, 'dist');
|
||||
const render = server({
|
||||
root,
|
||||
polyfill: false,
|
||||
dev: isDev,
|
||||
stream: true,
|
||||
});
|
||||
|
||||
const app = new Koa();
|
||||
app.use(
|
||||
compress({
|
||||
threshold: 2048,
|
||||
flush: require('zlib').Z_SYNC_FLUSH,
|
||||
}),
|
||||
);
|
||||
|
||||
app.use(async (ctx, next) => {
|
||||
const ext = extname(ctx.request.path);
|
||||
// 符合要求的路由才进行服务端渲染,否则走静态文件逻辑
|
||||
if (!ext) {
|
||||
ctx.type = 'text/html';
|
||||
ctx.status = 200;
|
||||
const { ssrStream } = await render({
|
||||
req: {
|
||||
url: ctx.request.url,
|
||||
},
|
||||
});
|
||||
|
||||
ctx.body = ssrStream;
|
||||
} else {
|
||||
await next();
|
||||
}
|
||||
});
|
||||
|
||||
app.use(mount('/dist', require('koa-static')(root)));
|
||||
|
||||
if (!process.env.NOW_ZEIT_ENV) {
|
||||
app.listen(3000);
|
||||
console.log('http://localhost:3000');
|
||||
}
|
||||
|
||||
module.exports = app.callback();
|
563
src/@app/app.js
563
src/@app/app.js
@ -1,16 +1,10 @@
|
||||
/**
|
||||
* @yCore_Worker
|
||||
*
|
||||
* @author rStudio© 2020
|
||||
* @license Pending...
|
||||
*/
|
||||
import * as Endpoints from 'globals/endpoints/index.js'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
import localforage from 'localforage'
|
||||
import { format } from 'timeago.js'
|
||||
import * as antd from 'antd'
|
||||
import moment from 'moment'
|
||||
import React from 'react'
|
||||
|
||||
import config from 'config'
|
||||
import './libs.js'
|
||||
@ -19,11 +13,11 @@ export * from '../../config/app.settings.js'
|
||||
export * from './libs.js'
|
||||
export * from 'utils'
|
||||
|
||||
export var endpoints = Endpoints
|
||||
|
||||
export const package_json = require('../../package.json')
|
||||
|
||||
export const UUAID = `${package_json.name}==${package_json.UUID}`
|
||||
export const endpoints = Endpoints
|
||||
|
||||
const prefix = package_json.name
|
||||
|
||||
export const AppInfo = {
|
||||
apid: package_json.name,
|
||||
@ -175,6 +169,18 @@ export function arrayRemoveByID(arr, value) {
|
||||
return ele.id != value
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Remove an element by key from an array
|
||||
*
|
||||
* @param array {array}
|
||||
* @param value {string}
|
||||
* @return object
|
||||
*/
|
||||
export function arrayRemoveByKEY(arr, value) {
|
||||
return arr.filter(function(ele) {
|
||||
return ele.key != value
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Global fix for convert '1, 0' to string boolean 'true, false'
|
||||
@ -208,83 +214,6 @@ export const time = {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Framework functionality for show with interface an notification
|
||||
*
|
||||
*/
|
||||
const {FieldTimeOutlined} = require('@ant-design/icons')
|
||||
export const notify = {
|
||||
expire: (...res) => {
|
||||
antd.notification.error({
|
||||
message: 'Hey ',
|
||||
icon: <FieldTimeOutlined />,
|
||||
description: res,
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
info: (...res) => {
|
||||
antd.notification.info({
|
||||
message: 'Well',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
exception: (...res) => {
|
||||
antd.notification.error({
|
||||
message: 'WoW!',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
warn: (...res) => {
|
||||
antd.notification.warn({
|
||||
message: 'Hey!',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
success: (...res) => {
|
||||
antd.notification.success({
|
||||
message: 'Well',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
error: (...res) => {
|
||||
antd.notification.error({
|
||||
message: 'Wopss',
|
||||
description: (
|
||||
<div>
|
||||
<span>An wild error appear! : </span>
|
||||
<br />
|
||||
<br />
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
backgroundColor: 'rgba(243, 19, 19, 0.329)',
|
||||
bottom: '0',
|
||||
color: 'black',
|
||||
padding: '3px',
|
||||
}}
|
||||
>
|
||||
{res.toString()}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
proccess: (...res) => {
|
||||
antd.notification.open({
|
||||
icon: <Icons.LoadingOutlined style={{ color: '#108ee9' }} />,
|
||||
message: 'Please wait',
|
||||
description: <div>{res}</div>,
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* User console with setting user permissions
|
||||
*
|
||||
@ -309,6 +238,35 @@ export const yconsole = {
|
||||
},
|
||||
}
|
||||
|
||||
export const __yconsole = {
|
||||
showLogs: SettingStoragedValue('force_showDevLogs')? true : false,
|
||||
log: (...cont) => {
|
||||
console.log(...cont)
|
||||
logger.consoles.indexeddb.log(...cont);
|
||||
},
|
||||
debug: (...cont) => {
|
||||
return logger.init(function() {
|
||||
logger.on(function() {
|
||||
console.debug(...cont);
|
||||
});
|
||||
}, null, {showLogs: yconsole.showLogs});
|
||||
},
|
||||
error: (...cont) => {
|
||||
return logger.init(function() {
|
||||
logger.on(function() {
|
||||
console.error(...cont);
|
||||
});
|
||||
}, null, {showLogs: yconsole.showLogs});
|
||||
},
|
||||
warn: (...cont) => {
|
||||
return logger.init(function() {
|
||||
logger.on(function() {
|
||||
console.warn(...cont);
|
||||
});
|
||||
}, null, {showLogs: yconsole.showLogs});
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Request FullScreen mode
|
||||
*
|
||||
@ -328,3 +286,432 @@ export function requestFullscreen() {
|
||||
elem.msRequestFullscreen()
|
||||
}
|
||||
}
|
||||
|
||||
export let logger = {
|
||||
/**
|
||||
* Is set with true or false after logger.init() invocation.
|
||||
*/
|
||||
isIndexedDBSupported: null,
|
||||
showLogs: true,
|
||||
|
||||
//// private variables
|
||||
databaseName: `${prefix}_ycoreLogger`,
|
||||
database: null,
|
||||
/**
|
||||
* Initializes window.indexedDB and logger.isIndexedDBSupported.
|
||||
* @param callbackSuccess invokes if browser supports IndexedDB.
|
||||
* @param callbackFail (optional) invokes if browser does not supports IndexedDB.
|
||||
*/
|
||||
init: function(callbackSuccess, callbackFail, options) {
|
||||
let indexedDB = window.indexedDB
|
||||
let IDBTransaction = window.IDBTransaction
|
||||
let IDBKeyRange = window.IDBKeyRange
|
||||
|
||||
// Check for options props
|
||||
if (options) {
|
||||
options.showLogs? logger.showLogs = options.showLogs : false
|
||||
}
|
||||
if (!indexedDB) {
|
||||
if(callbackFail) {callbackFail();}
|
||||
}
|
||||
else {
|
||||
if(!callbackSuccess) {
|
||||
throw "IllegalAgrumentException. Please provide a callback for success initialization";
|
||||
}
|
||||
callbackSuccess();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Turns on catching all console.* methods invocations and saving logs into IndexedDB
|
||||
* @param callback (optional) is invoked then database is successfully opened and console is replaced with logger.log2both.
|
||||
*/
|
||||
on: function(callback) {
|
||||
if( logger.consoles.originalIsOn === false ) {
|
||||
logger.consoles.originalIsOn = true;
|
||||
if( logger.database != null ) {
|
||||
logger.replaceConsoleThenOn(callback);
|
||||
}
|
||||
else {
|
||||
logger.openDb(logger.databaseName, function() {
|
||||
logger.replaceConsoleThenOn(callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
off: function() {
|
||||
if( logger.consoles.originalIsOn === true ) {
|
||||
console = logger.consoles.original;
|
||||
logger.consoles.originalIsOn = false;
|
||||
}
|
||||
},
|
||||
isOn: function() {
|
||||
return logger.consoles.originalIsOn;
|
||||
},
|
||||
clear: function() {
|
||||
if(logger.database == null) {
|
||||
throw "IllegalStateException: need to logger.init() and logger.on before clearing the database, e.g. logger.init(function(){logger.on(function(){logger.clear();});});";
|
||||
}
|
||||
logger.consoles.original.log("logger.clear");
|
||||
var objectStore = logger.database.transaction("logs").objectStore("logs");
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
var cursor = event.target.result;
|
||||
if (cursor) {
|
||||
// cursor.key + "=" + cursor.value
|
||||
var request = logger.database.transaction(["logs"], "readwrite").objectStore("logs").delete(cursor.key);
|
||||
request.onsuccess = function(event) {
|
||||
// It's gone!
|
||||
};
|
||||
cursor.continue();
|
||||
}
|
||||
else {
|
||||
logger.consoles.original.log("logs2indexeddb successfully cleared");
|
||||
}
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Opens a file with logs.
|
||||
* If parameters are null (not specified) then method downloads all logs from database.
|
||||
* If parameters are specified, then the method filters logs and provide only records
|
||||
* that were created since fromDate to toDate.
|
||||
* @param fromDate (optional)
|
||||
* @param toDate (optional)
|
||||
*/
|
||||
download: function(fromDate, toDate) {
|
||||
var fromTime = null;
|
||||
var toTime = null;
|
||||
if(fromDate != null) {
|
||||
if(toDate != null) {
|
||||
if(typeof(fromDate.getTime) === "undefined" || typeof(toDate.getTime) === "undefined" ) {
|
||||
throw "IllegalArgumentException: parameters must be Date objects";
|
||||
}
|
||||
fromTime = fromDate.getTime();
|
||||
toTime = toDate.getTime();
|
||||
}
|
||||
else {
|
||||
throw "IllegalArgumentException: Please provide either both parameters or none of them";
|
||||
}
|
||||
}
|
||||
var objectStore = logger.database.transaction("logs").objectStore("logs");
|
||||
|
||||
var data = '';
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
var cursor = event.target.result;
|
||||
if (cursor) {
|
||||
var v = cursor.value;
|
||||
if( fromTime == null || fromTime <= v.time && v.time <= toTime) {
|
||||
data += new Date(v.time*1)+" "+ v.label+" "+ v.log+"\n";
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
else {
|
||||
logger.downloadFile(data);
|
||||
}
|
||||
};
|
||||
},
|
||||
downloadToday: function() {
|
||||
var start = new Date();
|
||||
start.setHours(0,0,0,0);
|
||||
|
||||
var end = new Date();
|
||||
end.setHours(23,59,59,999);
|
||||
logger.download(start, end);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
downloadFile: function(data){
|
||||
if(!data) {
|
||||
logger.consoles.original.log("logger.download: Empty database");
|
||||
return;
|
||||
}
|
||||
var filename = 'console.log'
|
||||
|
||||
var blob = new Blob([data], {type: 'text/plain'}),
|
||||
e = document.createEvent('MouseEvents'),
|
||||
a = document.createElement('a')
|
||||
|
||||
a.download = filename
|
||||
a.href = window.URL.createObjectURL(blob)
|
||||
a.dataset.downloadurl = ['text/plain', a.download, a.href].join(':')
|
||||
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
|
||||
a.dispatchEvent(e)
|
||||
},
|
||||
clearAndDrop: function() {
|
||||
logger.clear();
|
||||
// todo replace with database drop
|
||||
},
|
||||
consoles: {
|
||||
originalIsOn: false,
|
||||
/**
|
||||
* @private Logs into both - console and indexeddb
|
||||
*/
|
||||
both: {
|
||||
log: function(str) {
|
||||
logger.showLogs ? logger.consoles.original.log(str) : null
|
||||
logger.consoles.indexeddb.log(str);
|
||||
},
|
||||
warn: function(str) {
|
||||
logger.showLogs ? logger.consoles.original.warn(str) : null
|
||||
logger.consoles.indexeddb.warn(str);
|
||||
},
|
||||
trace: function(str) {
|
||||
logger.showLogs ? logger.consoles.original.trace(str) : null
|
||||
logger.consoles.indexeddb.trace(str);
|
||||
},
|
||||
error: function(str) {
|
||||
logger.showLogs ? logger.consoles.original.error(str) : null
|
||||
logger.consoles.indexeddb.error(str);
|
||||
},
|
||||
info: function(str) {
|
||||
logger.showLogs ? logger.consoles.original.info(str) : null
|
||||
logger.consoles.indexeddb.info(str);
|
||||
},
|
||||
debug: function(str) {
|
||||
logger.showLogs ? logger.consoles.original.debug(str) : null
|
||||
logger.consoles.indexeddb.debug(str);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private Original console logger. No matter if logger is on or off. Is used for internal logger logging during test.
|
||||
*/
|
||||
original: console,
|
||||
/**
|
||||
* @public Logger that saves data into opened IndexedDB.
|
||||
*/
|
||||
indexeddb: {
|
||||
log: function(str) {
|
||||
logger.consoles.indexeddb.write2db('log', str);
|
||||
},
|
||||
warn: function(str) {
|
||||
logger.consoles.indexeddb.write2db('warn', str);
|
||||
},
|
||||
trace: function(str) {
|
||||
logger.consoles.indexeddb.write2db('trace', str);
|
||||
},
|
||||
error: function(str) {
|
||||
logger.consoles.indexeddb.write2db('error', str);
|
||||
},
|
||||
info: function(str) {
|
||||
logger.consoles.indexeddb.write2db('info', str);
|
||||
},
|
||||
debug: function(str) {
|
||||
logger.consoles.indexeddb.write2db('debug', str);
|
||||
},
|
||||
write2db: function(label, str) {
|
||||
var time = new Date();
|
||||
time.setMonth(time.getMonth()-1);
|
||||
var data = {
|
||||
time: time.getTime()+'',
|
||||
label: label,
|
||||
log: str
|
||||
};
|
||||
logger.database.transaction(["logs"], "readwrite").objectStore("logs").add(data);
|
||||
}
|
||||
}
|
||||
},
|
||||
exceptions: {
|
||||
uncatchable: {
|
||||
on: function() {
|
||||
if( logger.isOn() ) {
|
||||
window.onerror = logger.exceptions.uncatchable.onerror.both;
|
||||
}
|
||||
else {
|
||||
logger.consoles.original.warn("logger needs to be on to start catch uncatchable exceptions");
|
||||
}
|
||||
},
|
||||
off: function() {
|
||||
window.onerror = logger.exceptions.uncatchable.onerror.original;
|
||||
},
|
||||
onerror: {
|
||||
original: window.onerror,
|
||||
/**
|
||||
* Logs exception into the database
|
||||
*/
|
||||
custom: function (errorMsg, url, lineNumber) {
|
||||
logger.consoles.indexeddb.error(errorMsg+" "+url+" line:"+lineNumber);
|
||||
return false;
|
||||
},
|
||||
both: function (errorMsg, url, lineNumber) {
|
||||
logger.exceptions.uncatchable.onerror.custom("UNCATCHABLE: ----------------"+errorMsg, url, lineNumber);
|
||||
if( logger.exceptions.uncatchable.onerror.original ) {
|
||||
logger.exceptions.uncatchable.onerror.original(errorMsg, url, lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private Opens database and updates schema if needed.
|
||||
* @param dbName database name
|
||||
* @param callbackSuccessOpen (optional) invoked after success connect and update.
|
||||
* @param onupgradeneeded (optional) function to create different structure of the database.
|
||||
*/
|
||||
openDb: function(dbName, callbackSuccessOpen, onupgradeneeded) {
|
||||
logger.consoles.original.log("openDb ...");
|
||||
// Let us open our database
|
||||
var request = indexedDB.open(dbName, 2);
|
||||
request.onerror = function (event) {
|
||||
alert("Why didn't you allow my web app to use IndexedDB?!");
|
||||
logger.consoles.original.error("openDb:", event.target.errorCode);
|
||||
};
|
||||
request.onsuccess = function (e) {
|
||||
logger.database = request.result;
|
||||
logger.consoles.original.log("openDb DONE");
|
||||
logger.database.onerror = function (event) {
|
||||
// Generic error handler for all errors targeted at this database's
|
||||
// requests!
|
||||
logger.consoles.original.error("Database error: " + event.target.errorCode);
|
||||
};
|
||||
if(callbackSuccessOpen) {callbackSuccessOpen();}
|
||||
};
|
||||
// This event is only implemented in recent browsers
|
||||
request.onupgradeneeded = function (event) {
|
||||
logger.consoles.original.log("openDb.onupgradeneeded");
|
||||
var db = event.target.result;
|
||||
|
||||
var objectStore = db.createObjectStore("logs", { autoIncrement : true });
|
||||
|
||||
// Create an index to search by time
|
||||
objectStore.createIndex("time", "time", { unique: false });
|
||||
objectStore.createIndex("label", "label", { unique: false });
|
||||
|
||||
objectStore.transaction.oncomplete = function (event) {
|
||||
logger.consoles.original.log("openDb.onupgradeneeded.transaction.oncomplete");
|
||||
}
|
||||
};
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
replaceConsoleThenOn: function(callback) {
|
||||
console = logger.consoles.both;
|
||||
logger.exceptions.uncatchable.on();
|
||||
if( callback ) callback();
|
||||
},
|
||||
/**
|
||||
* Performance test methods.
|
||||
* Use
|
||||
* $(function () { // This is JQuery construction that needed to be sure that html document is loaded
|
||||
logger.init(function() {// successfully initialized
|
||||
logger.debug.startIndexedDBTest(5000, 'status');
|
||||
}, function() {// error
|
||||
window.alert("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.");
|
||||
logger.debug.status.html("<span style='color: red;>Error: Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.</span>");
|
||||
});
|
||||
});
|
||||
* <p id="status"></p>
|
||||
* to test 5000 writes.
|
||||
*/
|
||||
debug: {
|
||||
statusElementId: null,
|
||||
startTime: null,
|
||||
totalNumberOfWrites: null,
|
||||
|
||||
/**
|
||||
* Opens database and starts WriteTest
|
||||
* @param n number of records to write during the test.
|
||||
* @param statusElementId html element's id to write results of the test.
|
||||
*/
|
||||
startIndexedDBTest: function(n, statusElementId) {
|
||||
if( !n || !statusElementId ) {
|
||||
throw "IllegalArgumentsException";
|
||||
}
|
||||
logger.debug.statusElementId = statusElementId;
|
||||
logger.debug.status('Testing...');
|
||||
|
||||
logger.openDb("logs2indexeddb_test", function() {
|
||||
logger.debug.processWriteTest(logger.database, n);
|
||||
}, logger.debug.onupgradeneeded);
|
||||
},
|
||||
onupgradeneeded: function (event) {
|
||||
logger.consoles.original.log("debug.onupgradeneeded");
|
||||
var db = event.target.result;
|
||||
|
||||
// Create an objectStore to hold information about our customers. We're
|
||||
// going to use "ssn" as our key path because it's guaranteed to be
|
||||
// unique.
|
||||
var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
|
||||
|
||||
// Create an index to search customers by name. We may have duplicates
|
||||
// so we can't use a unique index.
|
||||
objectStore.createIndex("name", "name", { unique: false });
|
||||
|
||||
// Create an index to search customers by email. We want to ensure that
|
||||
// no two customers have the same email, so use a unique index.
|
||||
objectStore.createIndex("email", "email", { unique: true });
|
||||
|
||||
// Use transaction oncomplete to make sure the objectStore creation is
|
||||
// finished
|
||||
objectStore.transaction.oncomplete = function (event) {
|
||||
logger.consoles.original.log("debug.onupgradeneeded.transaction.oncomplete");
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
processWriteTest: function(db, n) {
|
||||
logger.consoles.original.log("processWriteTest");
|
||||
|
||||
logger.debug.status('Connected to database. Preparing to process ' + n + " writes.");
|
||||
alert("The test can take a lot of time (1-2 minutes). The browser can be locked duting the test. Ready to launch?");
|
||||
logger.debug.status("Testing... Please wait until test will be finished.");
|
||||
|
||||
logger.debug.totalNumberOfWrites = n;
|
||||
logger.debug.startTime = new Date();
|
||||
for (var i = 0; i < n; i++) {
|
||||
// status("Writing "+i+" record..."); // Comment this to get real time estimate
|
||||
logger.debug.processWrite(db, i);
|
||||
}
|
||||
// The write will be finished after last callback
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
testFinished: function () {
|
||||
logger.consoles.original.log("testFinished");
|
||||
var n = logger.debug.totalNumberOfWrites;
|
||||
var end = new Date();
|
||||
var diff = end.getMinutes() * 60 + end.getSeconds() - (logger.debug.startTime.getMinutes() * 60 + logger.debug.startTime.getSeconds());
|
||||
var mean = diff / n;
|
||||
|
||||
alert("Done. Check the result on the page.");
|
||||
logger.debug.status("One write request takes <b>" + mean + "</b> seconds.<br>Test time: " + diff + " seconds");
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
processWrite: function (db, i) {
|
||||
// logger.consoles.original.log("processWrite");
|
||||
var transaction = db.transaction(["customers"], "readwrite");
|
||||
|
||||
// Do something when all the data is added to the database.
|
||||
transaction.oncomplete = function (event) {
|
||||
// logger.consoles.original.log("processWrite.transaction.oncomplete");
|
||||
};
|
||||
|
||||
transaction.onerror = function (event) {
|
||||
// Don't forget to handle errors!
|
||||
// logger.consoles.original.error("processWrite.transaction.onerror: "+event.code);
|
||||
};
|
||||
|
||||
var objectStore = transaction.objectStore("customers");
|
||||
|
||||
var data = { ssn: i, name: "Bill", age: 35, email: "mail" + i + "@rtlservice.com" }
|
||||
var request = objectStore.put(data);
|
||||
request.onsuccess = function (event) {
|
||||
// event.target.result == customerData[i].ssn;
|
||||
// logger.consoles.original.log("processWrite.transaction...onsuccess: "+event.target.result);
|
||||
if (i == logger.debug.totalNumberOfWrites - 1) {
|
||||
logger.debug.testFinished();
|
||||
}
|
||||
};
|
||||
request.onerror = function () {
|
||||
logger.consoles.original.error("addPublication error", this.error);
|
||||
}
|
||||
},
|
||||
status: function (str) {
|
||||
document.getElementById(logger.debug.statusElementId).innerHTML = str;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,4 +2,5 @@
|
||||
export * from './libs/comty_ng/pre.js';
|
||||
export * from './libs/yulio_id/pre.js';
|
||||
export * from './libs/app_functions/pre.js';
|
||||
export * from './libs/api_call/pre.js';
|
||||
export * from './libs/api_call/pre.js';
|
||||
export * from './libs/apis/pre.js'
|
1
src/@app/libs/apis/pre.js
Normal file
1
src/@app/libs/apis/pre.js
Normal file
@ -0,0 +1 @@
|
||||
export * from './unsplash.js'
|
16
src/@app/libs/apis/unsplash.js
Normal file
16
src/@app/libs/apis/unsplash.js
Normal file
@ -0,0 +1,16 @@
|
||||
import axios from 'axios'
|
||||
import * as app from 'app'
|
||||
import keys from 'keys'
|
||||
|
||||
export const api_unsplash = {
|
||||
search: async (key, callback) => {
|
||||
if (!key) return false
|
||||
const response = await axios.get(app.endpoints.unsplash_endpoints.search, {
|
||||
params: { query: key},
|
||||
headers: {
|
||||
Authorization: `Client-ID ${keys.unsplash_key}`
|
||||
}
|
||||
})
|
||||
return callback(response.data.results)
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import styles from './modals.less';
|
||||
import classnames from 'classnames'
|
||||
|
||||
@ -19,12 +19,12 @@ class __Model_postreport extends React.PureComponent {
|
||||
return false
|
||||
}
|
||||
app.notify.info('This post has been reported successfully, our team will review it and inform you about problem resolution ...')
|
||||
app.FeedHandler.refresh()
|
||||
app.FeedHandler.goToElement(this.props.id)
|
||||
app.RenderFeed.RefreshFeed()
|
||||
app.RenderFeed.goToElement(this.props.id)
|
||||
}, payload)
|
||||
}
|
||||
setTimeout(() => {
|
||||
app.OverlaySwap.close()
|
||||
app.SwapMode.close()
|
||||
}, 500)
|
||||
|
||||
}
|
||||
@ -116,7 +116,7 @@ export const app_modals = {
|
||||
icon: <Icons.FrownOutlined />,
|
||||
content: 'It seems that you want to report this post, first of all it is necessary that you take into account that this tool is only intended for serious cases and we need you to comply with some questions to be able to report this post and to guarantee the quality of service ...',
|
||||
onOk() {
|
||||
return app.OverlaySwap.openFragment(<__Model_postreport id={post_id} />)
|
||||
return app.SwapMode.openFragment(<__Model_postreport id={post_id} />)
|
||||
},
|
||||
onCancel() {
|
||||
return false
|
||||
|
82
src/@app/libs/app_functions/notify.js
Normal file
82
src/@app/libs/app_functions/notify.js
Normal file
@ -0,0 +1,82 @@
|
||||
import { notification } from 'antd'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
export const notify = {
|
||||
fatal: (...res) => {
|
||||
notification.error({
|
||||
message: 'Fatal Error',
|
||||
icon: <Icons.Triangle style={{ color: '#fa8c16' }} />,
|
||||
description: res,
|
||||
placement: 'bottomLeft'
|
||||
})
|
||||
},
|
||||
expire: (...res) => {
|
||||
notification.error({
|
||||
message: 'Hey ',
|
||||
icon: <Icons.FieldTimeOutlined />,
|
||||
description: res,
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
info: (...res) => {
|
||||
notification.info({
|
||||
message: 'Well',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
exception: (...res) => {
|
||||
notification.error({
|
||||
message: 'WoW!',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
warn: (...res) => {
|
||||
notification.warn({
|
||||
message: 'Hey!',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
success: (...res) => {
|
||||
notification.success({
|
||||
message: 'Well',
|
||||
description: res.toString(),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
error: (...res) => {
|
||||
notification.error({
|
||||
message: 'Wopss',
|
||||
description: (
|
||||
<div>
|
||||
<span>An wild error appear! : </span>
|
||||
<br />
|
||||
<br />
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
backgroundColor: 'rgba(243, 19, 19, 0.329)',
|
||||
bottom: '0',
|
||||
color: 'black',
|
||||
padding: '3px',
|
||||
}}
|
||||
>
|
||||
{res.toString()}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
proccess: (...res) => {
|
||||
notification.open({
|
||||
icon: <Icons.LoadingOutlined style={{ color: '#108ee9' }} />,
|
||||
message: 'Please wait',
|
||||
description: <div>{res}</div>,
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
}
|
@ -1,53 +1,21 @@
|
||||
import { RenderFeed } from 'components/MainFeed'
|
||||
import { transitionToogle } from '../../../pages/login'
|
||||
import { SetControls, CloseControls } from 'components/Layout/ControlBar'
|
||||
import { SwapMode } from 'components/Layout/Overlay'
|
||||
|
||||
import umiRouter from 'umi/router'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import React from 'react'
|
||||
|
||||
import { SwapMode } from 'components/Layout/Overlay'
|
||||
import { RenderFeed } from 'components/MainFeed'
|
||||
import { updateTheme } from '../../../layouts/PrimaryLayout'
|
||||
|
||||
export * from './modals.js'
|
||||
export * from './notify.js'
|
||||
|
||||
export {SwapMode}
|
||||
|
||||
export function SetupApp() {
|
||||
// TODO: Default sets
|
||||
app.notify.success('Authorised, please wait...')
|
||||
const resourceLoad = localStorage.getItem('resource_bundle')
|
||||
if (!resourceLoad) {
|
||||
localStorage.setItem('resource_bundle', 'light_ng')
|
||||
}
|
||||
setTimeout(() => {
|
||||
app.router.push('main')
|
||||
}, 500)
|
||||
}
|
||||
|
||||
export const CheckThisApp = {
|
||||
desktop_mode: () => {
|
||||
const a = localStorage.getItem('desktop_src')
|
||||
if (a == 'true') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
}
|
||||
|
||||
export const OverlaySwap = {
|
||||
close: () => {
|
||||
SwapMode.close()
|
||||
},
|
||||
openPost: e => {
|
||||
SwapMode.openPost(e)
|
||||
},
|
||||
openSearch: e => {
|
||||
SwapMode.openSearch(e)
|
||||
},
|
||||
openFragment: e =>{
|
||||
SwapMode.openFragment(e)
|
||||
}
|
||||
}
|
||||
export {RenderFeed}
|
||||
|
||||
export const ControlBar = {
|
||||
set: e => {
|
||||
@ -58,30 +26,6 @@ export const ControlBar = {
|
||||
},
|
||||
}
|
||||
|
||||
export const FeedHandler = {
|
||||
refresh: () => {
|
||||
RenderFeed.RefreshFeed()
|
||||
},
|
||||
killByID: (post_id) => {
|
||||
RenderFeed.killByID(post_id)
|
||||
},
|
||||
addToRend: (payload) => {
|
||||
RenderFeed.addToRend(payload)
|
||||
},
|
||||
goToElement: post_id => {
|
||||
RenderFeed.goToElement(post_id)
|
||||
},
|
||||
sync: data => {
|
||||
RenderFeed.sync(data)
|
||||
}
|
||||
}
|
||||
|
||||
export const LoginPage = {
|
||||
transitionToogle: () => {
|
||||
transitionToogle()
|
||||
},
|
||||
}
|
||||
|
||||
export const router = {
|
||||
go: e => {
|
||||
goTo.element('primaryContent')
|
||||
@ -118,6 +62,7 @@ export const goTo = {
|
||||
try {
|
||||
document.getElementById(element).scrollIntoView()
|
||||
} catch (error) {
|
||||
console.debug(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -204,3 +149,52 @@ export const app_session = {
|
||||
},
|
||||
}
|
||||
|
||||
export const app_theme = {
|
||||
getString: () => {
|
||||
return localStorage.getItem('theme_style')
|
||||
},
|
||||
set: (data, process) => {
|
||||
if (!data){
|
||||
return false
|
||||
}
|
||||
let newdata = []
|
||||
if(process){
|
||||
let style = data
|
||||
let mix = []
|
||||
try {
|
||||
style[key] = value
|
||||
const obj = Object.entries(style)
|
||||
obj.forEach((e) => {
|
||||
mix.push({key: e[0], value: e[1]})
|
||||
})
|
||||
newdata = JSON.stringify(mix)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return false
|
||||
}
|
||||
}else{
|
||||
newdata = data
|
||||
}
|
||||
|
||||
localStorage.setItem('theme_style', newdata)
|
||||
app_theme.update()
|
||||
},
|
||||
getStyle: () => {
|
||||
let final = {}
|
||||
const storaged = localStorage.getItem('theme_style')
|
||||
if (storaged) {
|
||||
try {
|
||||
let scheme = JSON.parse(storaged)
|
||||
scheme.forEach((e)=>{
|
||||
final[e.key] = e.value
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
return final
|
||||
},
|
||||
update: () => {
|
||||
return updateTheme(app_theme.getStyle())
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { token_data } from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
export * from './comty_post.js'
|
||||
export * from './comty_user.js'
|
||||
|
@ -1,11 +0,0 @@
|
||||
const VerifiedBadge = () => (<svg xmlns="http://www.w3.org/2000/svg" fill="#55acee" width="15" height="15" viewBox="0 0 24 24"> <path d="M23 12l-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12m-13 5l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path></svg>)
|
||||
const CommonThings = () => (<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ff5991" d="M15,2C16.94,2 18.59,2.7 19.95,4.05C21.3,5.41 22,7.06 22,9C22,10.56 21.5,11.96 20.58,13.2C19.64,14.43 18.44,15.27 16.97,15.7L17,15.38V15C17,12.81 16.23,10.93 14.65,9.35C13.07,7.77 11.19,7 9,7H8.63L8.3,7.03C8.73,5.56 9.57,4.36 10.8,3.42C12.04,2.5 13.44,2 15,2M9,8A7,7 0 0,1 16,15A7,7 0 0,1 9,22A7,7 0 0,1 2,15A7,7 0 0,1 9,8M9,10A5,5 0 0,0 4,15A5,5 0 0,0 9,20A5,5 0 0,0 14,15A5,5 0 0,0 9,10Z"></path></svg>)
|
||||
const SunSVG = () => (<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 21 21"><g fill="none" fillRule="evenodd"><path fill="#fff" fillRule="nonzero" d="M21 10.5l-3 3V18h-4.5l-3 3-3-3H3v-4.5l-3-3 3-3V3h4.5l3-3 3 3H18v4.5z"></path><circle stroke="#000" strokeWidth="1.5" cx="10.5" cy="10.5" r="4"></circle></g></svg>)
|
||||
const MoonSVG = () => (<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 21 21"><g fill="none" fillRule="evenodd"><circle fill="#fff" cx="10.5" cy="10.5" r="10.5"></circle><path d="M13.396 11c0-3.019-1.832-5.584-4.394-6.566A6.427 6.427 0 0111.304 4C15.002 4 18 7.135 18 11c0 3.866-2.998 7-6.698 7A6.42 6.42 0 019 17.566c2.564-.98 4.396-3.545 4.396-6.566z" fill="#2F2E30" fillRule="nonzero"></path></g></svg>)
|
||||
const RobotOutlined = () => (<svg viewBox="64 64 896 896" focusable="false" data-icon="robot" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M300 328a60 60 0 10120 0 60 60 0 10-120 0zM852 64H172c-17.7 0-32 14.3-32 32v660c0 17.7 14.3 32 32 32h680c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32zm-32 660H204V128h616v596zM604 328a60 60 0 10120 0 60 60 0 10-120 0zm250.2 556H169.8c-16.5 0-29.8 14.3-29.8 32v36c0 4.4 3.3 8 7.4 8h729.1c4.1 0 7.4-3.6 7.4-8v-36c.1-17.7-13.2-32-29.7-32zM664 508H360c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h304c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"></path></svg>)
|
||||
const SavedPost = () => (<svg viewBox="0 0 24 24" focusable="false" width="1em" height="1em" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" ><path d="M4 3h16a2 2 0 0 1 2 2v6a10 10 0 0 1-10 10A10 10 0 0 1 2 11V5a2 2 0 0 1 2-2z"></path><polyline points="8 10 12 14 16 10"></polyline></svg>)
|
||||
const SavedPostColor = () => (<svg viewBox="0 0 24 24" focusable="false" width="1em" height="1em" fill="rgb(230, 247, 255)" stroke="rgb(24, 144, 255)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" ><path d="M4 3h16a2 2 0 0 1 2 2v6a10 10 0 0 1-10 10A10 10 0 0 1 2 11V5a2 2 0 0 1 2-2z"></path><polyline points="8 10 12 14 16 10"></polyline></svg>)
|
||||
const SavedPostGrey = () => (<svg viewBox="0 0 24 24" focusable="false" width="1em" height="1em" fill="rgb(196, 196, 196)" stroke="rgba(133, 133, 133, 1)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" ><path d="M4 3h16a2 2 0 0 1 2 2v6a10 10 0 0 1-10 10A10 10 0 0 1 2 11V5a2 2 0 0 1 2-2z"></path><polyline points="8 10 12 14 16 10"></polyline></svg>)
|
||||
|
||||
const CustomIcons = {SavedPostGrey, SavedPostColor, VerifiedBadge, CommonThings, SunSVG, MoonSVG, RobotOutlined, SavedPost}
|
||||
export default CustomIcons
|
@ -3,7 +3,7 @@ import * as antd from 'antd'
|
||||
import * as app from 'app'
|
||||
import styles from './index.less'
|
||||
import classnames from 'classnames'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
export const SetHeaderSearchType = {
|
||||
disable: () => {
|
||||
|
8
src/components/Icons/custom.js
Normal file
8
src/components/Icons/custom.js
Normal file
@ -0,0 +1,8 @@
|
||||
export const VerifiedBadge = () => (<svg xmlns="http://www.w3.org/2000/svg" fill="#55acee" width="15" height="15" viewBox="0 0 24 24"> <path d="M23 12l-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12m-13 5l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path></svg>)
|
||||
export const Patreon = () => (<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 100 96">
|
||||
<g fill="currentColor" fill-rule="evenodd">
|
||||
<path d="M64.1102,0.1004 C44.259,0.1004 28.1086,16.2486 28.1086,36.0986 C28.1086,55.8884 44.259,71.989 64.1102,71.989 C83.9,71.989 100,55.8884 100,36.0986 C100,16.2486 83.9,0.1004 64.1102,0.1004"/>
|
||||
<polygon points=".012 95.988 17.59 95.988 17.59 .1 .012 .1"/>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
4
src/components/Icons/index.js
Normal file
4
src/components/Icons/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
export * from 'feather-reactjs'
|
||||
export * from '@ant-design/icons'
|
||||
export * from './custom'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import styles from '../index.less'
|
||||
|
||||
export interface Card_Component_props {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import styles from '../../index.less'
|
||||
import classnames from 'classnames'
|
||||
import reactable from 'reactablejs'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import styles from '../../index.less'
|
||||
import classnames from 'classnames'
|
||||
import reactable from 'reactablejs'
|
||||
|
@ -11,7 +11,7 @@
|
||||
border: 0!important;
|
||||
outline: 0!important;
|
||||
color: #273346;
|
||||
padding: 0 48px;
|
||||
padding: 0 0 0 48px;
|
||||
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 56.966 56.966' fill='%23c1c7cd'%3e%3cpath d='M55.146 51.887L41.588 37.786A22.926 22.926 0 0046.984 23c0-12.682-10.318-23-23-23s-23 10.318-23 23 10.318 23 23 23c4.761 0 9.298-1.436 13.177-4.162l13.661 14.208c.571.593 1.339.92 2.162.92.779 0 1.518-.297 2.079-.837a3.004 3.004 0 00.083-4.242zM23.984 6c9.374 0 17 7.626 17 17s-7.626 17-17 17-17-7.626-17-17 7.626-17 17-17z'/%3e%3c/svg%3e");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
|
@ -3,58 +3,26 @@ import styles from './__priPost.less'
|
||||
|
||||
import * as antd from 'antd'
|
||||
import * as app from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
|
||||
import { MediaPlayer } from 'components'
|
||||
|
||||
const VerifiedBadge = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="#55acee"
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M23 12l-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12m-13 5l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path>
|
||||
</svg>
|
||||
)
|
||||
import { MediaPlayer, PostCard } from 'components'
|
||||
|
||||
export default class __priPost extends React.PureComponent {
|
||||
renderContent(payload) {
|
||||
const { id, postText, postFile_full, post_time, publisher } = payload
|
||||
const {isMobile}= this.props
|
||||
|
||||
return (
|
||||
<div className={styles.contentWrapper}>
|
||||
{postFile_full ? <MediaPlayer isMobile={isMobile} entire={true} file={postFile_full} /> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {payload} = this.props
|
||||
if (!payload) {
|
||||
return <h1>This post not exists!!!</h1>
|
||||
}
|
||||
const { id, postText, postFile_full, post_time, publisher } = payload
|
||||
const {isMobile}= this.props
|
||||
|
||||
return (
|
||||
<div className={styles.render_component}>
|
||||
<div className={styles.UserContainer}>
|
||||
<div className={styles.UserContainer_text}>
|
||||
<h4 className={styles.titleUser}>
|
||||
{publisher.username}{' '}
|
||||
{app.booleanFix(publisher.verified) ? (
|
||||
<Icon style={{ color: 'blue' }} component={VerifiedBadge} />
|
||||
) : null}
|
||||
</h4>
|
||||
<p>
|
||||
{post_time} {app.IsThisUser.dev() ? `| #${id}` : null}{' '}
|
||||
</p>
|
||||
</div>
|
||||
<antd.Avatar shape="square" size={50} src={publisher.avatar} />
|
||||
<div className={styles.contentWrapper}>
|
||||
<div className={styles.contentBody}>
|
||||
<PostCard id="post_card" payload={payload} key={id} />
|
||||
</div>
|
||||
{this.renderContent(payload)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,33 +1,27 @@
|
||||
@import '~themes/index.less';
|
||||
|
||||
.contentWrapper {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
height: 100%;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
|
||||
background: rgba(158, 158, 158, 0.5); // Make sure this color has an opacity of less than 1
|
||||
backdrop-filter: blur(10px); // This be the blur
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all @__Global_SwapAnimDuration ease-in-out;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.UserContainer {
|
||||
display: flex;
|
||||
.contentBody{
|
||||
|
||||
position: relative;
|
||||
float: right;
|
||||
z-index: 150;
|
||||
transform: translate(0, -40px);
|
||||
|
||||
.UserContainer_text {
|
||||
margin: 0 8px;
|
||||
|
||||
h4 {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
p {
|
||||
word-break: break-all;
|
||||
text-align: right;
|
||||
font-size: 11px;
|
||||
color: #eeeeee !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
width: calc(100% - @Overlay_container2_active_width);
|
||||
}
|
@ -72,16 +72,18 @@ export default class __priSearch extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
EntryComponent = (t, source) => {
|
||||
function onclick(e){
|
||||
|
||||
function goToEntry(e){
|
||||
if(!e) return false
|
||||
app.router.go(`@${e}`)
|
||||
}
|
||||
|
||||
try {
|
||||
return (
|
||||
<antd.List
|
||||
dataSource={source}
|
||||
renderItem={item =>
|
||||
<div id={item.id} className={styles.search_card} onClick={() => onclick(item.username) }>
|
||||
<div id={item.id} className={styles.search_card} onClick={() => goToEntry(item.username) }>
|
||||
<div className={styles.search_title}>
|
||||
<img src={item.avatar} />
|
||||
<p className={styles.search_user_username}>
|
||||
|
@ -4,7 +4,7 @@ import { SearchCard, Feather } from 'components'
|
||||
|
||||
import * as antd from 'antd'
|
||||
import * as app from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
|
||||
const VerifiedBadge = () => (
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import styles from './index.less'
|
||||
import classnames from 'classnames'
|
||||
import reactable from 'reactablejs'
|
||||
@ -111,7 +111,7 @@ export const SwapMode = {
|
||||
<h2>
|
||||
<Icons.SearchOutlined /> Results of {id || '... nothing ?'}
|
||||
</h2>
|
||||
<__priSearch lost_focus={() => SwapMode.close()} payload={tmp} />
|
||||
<__priSearch payload={tmp} />
|
||||
</div>
|
||||
|
||||
return OverlayLayoutComponent.setState({
|
||||
|
@ -51,12 +51,12 @@
|
||||
.Overlay_wrapper {
|
||||
right: 0;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
|
||||
z-index: 50;
|
||||
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
max-width: @Overlay_wrapper_maxwidth;
|
||||
|
||||
// 150px extra for left-sider
|
||||
width: calc( 100% + 150px );
|
||||
backdrop-filter: blur(2px);
|
||||
&.mobile{
|
||||
overflow-y: scroll;
|
||||
flex-direction: column;
|
||||
@ -67,13 +67,14 @@
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: none;
|
||||
width: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.expand{
|
||||
max-width: calc(@Overlay_wrapper_maxwidth + 150px);
|
||||
max-width: calc(100% + 150px);
|
||||
}
|
||||
|
||||
|
||||
transition: all @__Global_SwapAnimDuration ease-in-out;
|
||||
}
|
||||
@ -82,25 +83,40 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
max-width: @Overlay_wrapper_maxwidth;
|
||||
min-width: 200px;
|
||||
|
||||
display: flex;
|
||||
z-index: 50;
|
||||
|
||||
right: 0;
|
||||
padding: 30px 30px 30px 35px;
|
||||
|
||||
|
||||
@media (max-width: @bp-medium) {
|
||||
padding: 30px 5px 30px 5px;
|
||||
}
|
||||
|
||||
color: @Overlay_container1_def_color;
|
||||
background-color: #F8F6F8;
|
||||
|
||||
&.half {
|
||||
background-color: #2d2d2d;
|
||||
color: @Overlay_container1_active_color;
|
||||
max-width: calc(100% + 150px);
|
||||
}
|
||||
|
||||
&.full_open {
|
||||
width: @Overlay_wrapper_showFull_width;
|
||||
max-width: none;
|
||||
background-color: transparent;
|
||||
position: absolute;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
&.mobile {
|
||||
min-width: unset;
|
||||
max-width: unset;
|
||||
|
||||
width: 100%;
|
||||
height: 0;
|
||||
bottom: 0;
|
||||
|
@ -1,22 +1,77 @@
|
||||
import React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
import Icon from '@ant-design/icons'
|
||||
|
||||
import { withI18n, Trans } from '@lingui/react'
|
||||
import styles from './default.less'
|
||||
import * as app from 'app'
|
||||
import CustomIcons from '../../CustomIcons'
|
||||
import classnames from 'classnames'
|
||||
|
||||
@withI18n()
|
||||
export default class Sider_Default extends React.PureComponent {
|
||||
state = {
|
||||
loading: true,
|
||||
menus: null
|
||||
}
|
||||
|
||||
require(e){
|
||||
switch (e) {
|
||||
case 'login':
|
||||
return true
|
||||
case 'admin':
|
||||
return true
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
try {
|
||||
let tmp = [];
|
||||
const { menus } = this.props
|
||||
menus.forEach(e => {
|
||||
if (this.require(e.require)) {
|
||||
tmp.push(e)
|
||||
}
|
||||
});
|
||||
this.setState({ menus: tmp, loading: false })
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
renderMenus(data){
|
||||
try {
|
||||
return data.map(e => {
|
||||
return(
|
||||
<antd.Menu.Item key={e.id}>
|
||||
{e.icon}
|
||||
<Trans>
|
||||
<span>{e.title}</span>
|
||||
</Trans>
|
||||
</antd.Menu.Item>
|
||||
)
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { handleClickMenu, logo } = this.props
|
||||
const { handleClickMenu, logo, theme } = this.props
|
||||
const predominantColor = theme.predominantColor || "#333"
|
||||
|
||||
if (this.state.loading) return <div>Loading</div>
|
||||
return (
|
||||
<div className={styles.left_sider_wrapper}>
|
||||
<antd.Layout.Sider
|
||||
trigger={null}
|
||||
className={styles.left_sider_container}
|
||||
style={{ flex:'unset', maxWidth: 'unset', minWidth: '200px', width: '100%'}}
|
||||
>
|
||||
<div className={styles.left_sider_brandholder}>
|
||||
<img
|
||||
@ -28,40 +83,14 @@ export default class Sider_Default extends React.PureComponent {
|
||||
<div className={styles.left_sider_menuContainer}>
|
||||
|
||||
<antd.Menu
|
||||
selectable={false}
|
||||
// style={{color: predominantColor}}
|
||||
//className={classnames(styles.left_sider_menuItems, {[styles.matchColor]: theme.predominantColor? true : false})}
|
||||
selectable={true}
|
||||
className={styles.left_sider_menuItems}
|
||||
mode="vertical"
|
||||
onClick={handleClickMenu}
|
||||
>
|
||||
<antd.Menu.Item key="explore">
|
||||
<Icons.CompassTwoTone twoToneColor={"#28c35d"} />
|
||||
<Trans>
|
||||
<span>Explore</span>
|
||||
</Trans>
|
||||
</antd.Menu.Item>
|
||||
|
||||
<antd.Menu.Item key="saves">
|
||||
<Icon component={CustomIcons.SavedPostColor} />
|
||||
<Trans>
|
||||
<span>Saves</span>
|
||||
</Trans>
|
||||
</antd.Menu.Item>
|
||||
|
||||
|
||||
<antd.Menu.Item key="marketplace">
|
||||
<Icons.ShoppingTwoTone twoToneColor={"#ff7a45"}/>
|
||||
<Trans>
|
||||
<span>Marketplace</span>
|
||||
</Trans>
|
||||
</antd.Menu.Item>
|
||||
|
||||
|
||||
<antd.Menu.Item key="chats">
|
||||
<Icons.MessageTwoTone twoToneColor={"#ff4d4f"}/>
|
||||
<Trans>
|
||||
<span>Chats</span>
|
||||
</Trans>
|
||||
</antd.Menu.Item>
|
||||
{this.renderMenus(this.state.menus)}
|
||||
|
||||
</antd.Menu>
|
||||
|
||||
@ -69,8 +98,9 @@ export default class Sider_Default extends React.PureComponent {
|
||||
<antd.Menu
|
||||
selectable={false}
|
||||
className={styles.left_sider_menuItems}
|
||||
mode="horizontal"
|
||||
mode="vertical"
|
||||
onClick={handleClickMenu}
|
||||
|
||||
>
|
||||
<antd.Menu.Item key="general_settings">
|
||||
<Icons.SettingOutlined />
|
||||
|
@ -5,36 +5,68 @@
|
||||
border-color: transparent;
|
||||
font-size: 13px;
|
||||
font-family: @__Global_general_font_family;
|
||||
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
|
||||
z-index: 40;
|
||||
float: left;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
backdrop-filter: blur(2px);
|
||||
|
||||
&.matchColor{
|
||||
h1,h2,h3,h4,h5,span,p,svg {
|
||||
color: unset;
|
||||
filter: invert(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:global {
|
||||
.ant-layout-sider {
|
||||
background-color: @left_sider_backgroud;
|
||||
|
||||
background-color: transparent;
|
||||
float: right;
|
||||
.ant-menu {
|
||||
vertical-align: middle;
|
||||
margin: 0 0 0 5px;
|
||||
// margin: 0 0 0 5px;
|
||||
}
|
||||
|
||||
.ant-menu-item {
|
||||
color: #333;
|
||||
|
||||
|
||||
transition: @transition-ease-inout;
|
||||
|
||||
border-radius: 4px 8px 8px 4px;
|
||||
padding: 2px 0 2px 24px;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ant-menu-item:hover {
|
||||
border-radius: 8px 8px 8px 8px;
|
||||
transform: translate(10px,0);
|
||||
|
||||
// background: linear-gradient(49deg, rgba(255,255,255,1) 32%, rgba(255, 255, 255, 0) 100%);
|
||||
backdrop-filter: blur(2px);
|
||||
border-left: 10px #FFCC00 solid;
|
||||
color: rgb(102, 102, 102);
|
||||
}
|
||||
|
||||
.ant-menu-item-selected {
|
||||
background-color: unset;
|
||||
// background: linear-gradient(90deg, rgb(255, 230, 0) 2%, rgba(255,255,255,0.5) 10%);
|
||||
|
||||
}
|
||||
|
||||
.anticon {
|
||||
font-size: @left_sider_sizeIcons;
|
||||
}
|
||||
|
||||
|
||||
.ant-menu-inline-collapsed,
|
||||
.antd-menu-vertical-left,
|
||||
.ant-menu-vertical {
|
||||
:hover {
|
||||
background-color: @left_sider_menu__onhover_backgroud;
|
||||
color: @left_sider_menu__onhover_color;
|
||||
}
|
||||
|
||||
border-right: 0 solid transparent;
|
||||
}
|
||||
}
|
||||
@ -45,14 +77,11 @@
|
||||
.left_sider_brandholder {
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
display: flex;
|
||||
vertical-align: middle;
|
||||
padding: 5px;
|
||||
margin: 7px auto 15px auto;
|
||||
width: 100%;
|
||||
max-height: 58px;
|
||||
transform: translate(2px, 0);
|
||||
img{
|
||||
margin: 7px 0 0 20px;
|
||||
max-height: 70px;
|
||||
height: 7vh;
|
||||
filter: drop-shadow(1px 0px 1px #b9b9b9);
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,9 +97,8 @@
|
||||
}
|
||||
.ant-menu-item{
|
||||
height: 35px!important;
|
||||
line-height: 0px!important;
|
||||
padding: 0!important;
|
||||
margin: 0!important;
|
||||
margin-bottom: 0!important;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,8 +112,6 @@
|
||||
.left_sider_menuContainer {
|
||||
height: 100%;
|
||||
margin: 18px 0 8px 0;
|
||||
|
||||
overflow-x: hidden;
|
||||
flex: 1;
|
||||
|
||||
:global {
|
||||
@ -126,12 +152,5 @@
|
||||
|
||||
animation: fadein 0.5s;
|
||||
|
||||
:global {
|
||||
.ant-menu-item {
|
||||
padding: 0 !important;
|
||||
margin: 2px auto 2px 24px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +1,29 @@
|
||||
import React from 'react'
|
||||
import config from 'config'
|
||||
import * as app from 'app'
|
||||
import MenuList from 'globals/sidebar_menu'
|
||||
|
||||
import Sider_Mobile from './mobile.js'
|
||||
import Sider_Default from './default.js'
|
||||
|
||||
class Sider extends React.PureComponent {
|
||||
|
||||
onClickFunctions = {
|
||||
saves: (e) => {
|
||||
this.setState({selectedKey: e})
|
||||
app.router.go('saves')
|
||||
},
|
||||
events: (e) => {
|
||||
this.setState({selectedKey: e})
|
||||
app.router.go('events')
|
||||
},
|
||||
marketplace: (e) => {
|
||||
this.setState({selectedKey: e})
|
||||
app.router.go('marketplace')
|
||||
},
|
||||
explore: (e) => {
|
||||
this.setState({selectedKey: e})
|
||||
app.router.go('main')
|
||||
},
|
||||
chats: (e) => {
|
||||
this.setState({selectedKey: e})
|
||||
app.router.go('chats')
|
||||
}
|
||||
}
|
||||
|
||||
handleClickMenu = e => {
|
||||
e.key === 'chats' && this.onClickFunctions.chats(e.key)
|
||||
e.key === 'messages' && app.router.go('messages')
|
||||
e.key === 'SignOut' && app.app_session.logout()
|
||||
e.key === 'general_settings' && app.router.go('settings')
|
||||
e.key === 'profile' && app.router.goprofile()
|
||||
e.key === 'saves' && this.onClickFunctions.saves(e.key)
|
||||
e.key === 'events' && this.onClickFunctions.events(e.key)
|
||||
e.key === 'marketplace' && this.onClickFunctions.marketplace(e.key)
|
||||
e.key === 'explore' && this.onClickFunctions.explore(e.key)
|
||||
e.key === 'debug_area' && app.router.go('__m')
|
||||
e.key === 'saves' && app.router.go('saves')
|
||||
e.key === 'main' && app.router.go('main')
|
||||
e.key === 'explore' && app.router.go('explore')
|
||||
e.key === 'notifications' && app.router.go('notifications')
|
||||
e.key === 'debug_area' && app.router.go('debug')
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isMobile } = this.props
|
||||
const sider_props = {handleClickMenu: this.handleClickMenu ,logo: config.LogoPath, menulist: null, userData: this.props.userData}
|
||||
|
||||
const { isMobile, theme } = this.props
|
||||
const sider_props = {theme: theme, menus: MenuList, handleClickMenu: this.handleClickMenu ,logo: config.LogoPath, menulist: null, userData: this.props.userData}
|
||||
|
||||
if (isMobile) {
|
||||
return <Sider_Mobile {...sider_props} />
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
|
||||
import { withI18n, Trans } from '@lingui/react'
|
||||
import styles from './mobile.less'
|
||||
import * as app from 'app'
|
||||
import CustomIcons from '../../CustomIcons'
|
||||
|
||||
|
||||
@withI18n()
|
||||
export default class Sider_Mobile extends React.PureComponent {
|
||||
|
@ -125,6 +125,7 @@ class MainFeed extends React.PureComponent {
|
||||
more(fkey){
|
||||
try {
|
||||
const { get, uid, filters } = this.props
|
||||
console.log(get)
|
||||
if (!get) {
|
||||
app.yconsole.error('Please, fill params with an catch type...')
|
||||
return
|
||||
@ -154,7 +155,7 @@ class MainFeed extends React.PureComponent {
|
||||
return true
|
||||
}, payload)
|
||||
} catch (err) {
|
||||
app.notify.error(err)
|
||||
app.notify.error('[ MainFeed ]', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import styles from './index.less'
|
||||
import { CustomIcons, Like_button, MediaPlayer } from 'components'
|
||||
import { Like_button, MediaPlayer } from 'components'
|
||||
import * as Icons from 'components/Icons'
|
||||
import * as app from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
import classnames from 'classnames'
|
||||
import * as MICON from '@material-ui/icons'
|
||||
@ -11,11 +11,21 @@ import * as MICON from '@material-ui/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: 'Empty',
|
||||
const defaultPayload = {
|
||||
id: null,
|
||||
post_time: null,
|
||||
postText: null,
|
||||
postFile: null,
|
||||
publisher: null,
|
||||
post_likes: null,
|
||||
is_post_pinned: null,
|
||||
is_liked: null,
|
||||
post_comments: null,
|
||||
get_post_comments: null,
|
||||
postPinned: false,
|
||||
postReported: false,
|
||||
postBoosted: false,
|
||||
ReportIgnore: false,
|
||||
}
|
||||
|
||||
class PostCard extends React.PureComponent {
|
||||
@ -23,13 +33,36 @@ class PostCard extends React.PureComponent {
|
||||
super(props),
|
||||
this.state = {
|
||||
visibleMoreMenu: false,
|
||||
postPinned: this.props.payload.is_post_pinned,
|
||||
postSaved: this.props.payload.is_post_saved,
|
||||
postReported: this.props.payload.is_post_reported,
|
||||
postBoosted: this.props.payload.is_post_boosted,
|
||||
ReportIgnore: false,
|
||||
payload: this.props.payload,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
const a = this.props.payload
|
||||
const b = defaultPayload
|
||||
try {
|
||||
if(a){
|
||||
let tmp;
|
||||
const propsArray = Object.keys(a)
|
||||
const defaultArray = Object.keys(b)
|
||||
propsArray.forEach(e => {
|
||||
if (defaultArray.includes(e)){
|
||||
tmp[e] = "something"
|
||||
}
|
||||
|
||||
})
|
||||
console.log(tmp)
|
||||
}
|
||||
|
||||
else{
|
||||
console.warn('Empty payload, setting default...')
|
||||
this.setState({ payload: b})
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
handleVisibleChange = flag => {
|
||||
this.setState({ visibleMoreMenu: flag });
|
||||
};
|
||||
@ -39,10 +72,9 @@ class PostCard extends React.PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { payload, customActions } = this.props
|
||||
const { payload } = this.state
|
||||
const ActShowMode = app.AppSettings.auto_hide_postbar
|
||||
|
||||
const post_data = payload || emptyPayload;
|
||||
const {
|
||||
id,
|
||||
post_time,
|
||||
@ -54,14 +86,17 @@ class PostCard extends React.PureComponent {
|
||||
is_liked,
|
||||
post_comments,
|
||||
get_post_comments
|
||||
} = post_data
|
||||
} = payload || defaultPayload
|
||||
|
||||
if(!id, !postText, !postFile, !publisher) return null
|
||||
|
||||
|
||||
const SwapThisPost = () => {
|
||||
localStorage.setItem('p_back_uid', id)
|
||||
if (postFile){
|
||||
app.SwapMode.openPost(id, post_data)
|
||||
}
|
||||
|
||||
app.SwapMode.openPost(id, payload)
|
||||
app.SwapMode.openComments(id)
|
||||
|
||||
}
|
||||
|
||||
const handlePostActions = {
|
||||
@ -71,7 +106,7 @@ class PostCard extends React.PureComponent {
|
||||
if (err) {
|
||||
return false
|
||||
}
|
||||
app.FeedHandler.killByID(post_id)
|
||||
app.RenderFeed.killByID(post_id)
|
||||
}, payload)
|
||||
},
|
||||
save: post_id => {
|
||||
@ -110,7 +145,7 @@ class PostCard extends React.PureComponent {
|
||||
}, payload)
|
||||
},
|
||||
}
|
||||
const defaultActions = [
|
||||
const actions = [
|
||||
<div>
|
||||
<Like_button
|
||||
count={post_likes}
|
||||
@ -123,7 +158,6 @@ class PostCard extends React.PureComponent {
|
||||
<MICON.InsertComment key="comments" onClick={() => SwapThisPost()} />
|
||||
</antd.Badge>,
|
||||
]
|
||||
const actions = customActions || defaultActions
|
||||
|
||||
const MoreMenu = (
|
||||
<antd.Menu >
|
||||
@ -223,7 +257,7 @@ class PostCard extends React.PureComponent {
|
||||
{app.booleanFix(publisher.verified) ? (
|
||||
<Icon
|
||||
style={{ color: 'blue' }}
|
||||
component={CustomIcons.VerifiedBadge}
|
||||
component={Icons.VerifiedBadge}
|
||||
/>
|
||||
) : null}
|
||||
{app.booleanFix(publisher.nsfw_flag) ? (
|
||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as app from 'app'
|
||||
import styles from './index.less'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
import $ from 'jquery'
|
||||
import * as MICONS from '@material-ui/icons'
|
||||
@ -155,7 +155,7 @@ class PostCreator extends React.PureComponent {
|
||||
setTimeout(() => {
|
||||
this.setState({ posting_ok: false })
|
||||
}, 1000)
|
||||
app.FeedHandler.refresh()
|
||||
app.RenderFeed.RefreshFeed()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -220,7 +220,7 @@ class PostCreator extends React.PureComponent {
|
||||
)
|
||||
}
|
||||
this.FlushPostState()
|
||||
// app.FeedHandler.addToRend(JSON.parse(res)['data'])
|
||||
// app.RenderFeed.addToRend(JSON.parse(res)['data'])
|
||||
}, payload)
|
||||
}
|
||||
dropRef = React.createRef()
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as app from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { Post_Options } from 'globals/post_options.js'
|
||||
import styles from './post_options.less'
|
||||
|
@ -2,8 +2,7 @@ import React from 'react'
|
||||
import styles from './styles.less'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import { CustomIcons, MainFeed, PostCreator } from 'components'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import { Icons, MainFeed, PostCreator } from 'components'
|
||||
import Icon from '@ant-design/icons'
|
||||
import Follow_btn from './components/Follow_btn.js'
|
||||
import { BadgesType } from 'globals/badges_list'
|
||||
@ -199,7 +198,7 @@ className={classnames(styles.userWrapper, {
|
||||
color: 'blue',
|
||||
verticalAlign: 'top',
|
||||
}}
|
||||
component={CustomIcons.VerifiedBadge}
|
||||
component={Icons.VerifiedBadge}
|
||||
/>
|
||||
) : null}
|
||||
</antd.Tooltip>
|
||||
|
@ -1,7 +1,7 @@
|
||||
// @alias from 'components'
|
||||
|
||||
// Helpers & Misc
|
||||
import CustomIcons from './CustomIcons'
|
||||
export * as Icons from './Icons'
|
||||
import Loader from './Loader/Loader.js'
|
||||
import App_about from './App_about'
|
||||
import * as Feather from 'feather-reactjs'
|
||||
@ -35,7 +35,6 @@ export {
|
||||
Loader,
|
||||
PostCard,
|
||||
PostCreator,
|
||||
CustomIcons,
|
||||
Like_button,
|
||||
MainFeed,
|
||||
}
|
||||
|
@ -21,13 +21,21 @@ import styles from './PrimaryLayout.less'
|
||||
const { Content } = antd.Layout
|
||||
const { Sider, Control, Overlay, WindowAppBar } = MyLayout
|
||||
|
||||
export function updateTheme(data){
|
||||
if (!data) return false
|
||||
console.log(data)
|
||||
return PrimaryComponent.setState({theme: data})
|
||||
}
|
||||
|
||||
|
||||
@withRouter
|
||||
@connect(({ app, loading }) => ({ app, loading }))
|
||||
class PrimaryLayout extends React.Component {
|
||||
class PrimaryLayout extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
window.PrimaryComponent = this
|
||||
this.state = {
|
||||
theme: app.app_theme.getStyle(),
|
||||
collapsed: app.AppSettings.default_collapse_sider ? true : false,
|
||||
isMobile: false,
|
||||
desktop_mode: false,
|
||||
@ -36,6 +44,7 @@ class PrimaryLayout extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
this.setState({
|
||||
userData: app.userData(),
|
||||
})
|
||||
@ -62,12 +71,22 @@ class PrimaryLayout extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { app, location, dispatch, children } = this.props
|
||||
const { userData, collapsed, isMobile } = this.state
|
||||
const { location, dispatch, children } = this.props
|
||||
const { userData, collapsed, isMobile, theme, predominantColor } = this.state
|
||||
const { onCollapseChange } = this
|
||||
const { theme } = app
|
||||
|
||||
|
||||
|
||||
const SiderProps = {
|
||||
breakpoint:{
|
||||
xs: '480px',
|
||||
sm: '576px',
|
||||
md: '768px',
|
||||
lg: '992px',
|
||||
xl: '1200px',
|
||||
xxl: '1600px',
|
||||
},
|
||||
predominantColor,
|
||||
theme,
|
||||
userData,
|
||||
isMobile,
|
||||
@ -85,13 +104,13 @@ class PrimaryLayout extends React.Component {
|
||||
userData,
|
||||
isMobile,
|
||||
}
|
||||
|
||||
console.log(theme)
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className={classnames(styles.__ControlBar, {[styles.mobile]: isMobile})}>
|
||||
<Control mobile={isMobile} />
|
||||
</div>
|
||||
<antd.Layout id="primaryLayout" className={classnames(styles.primary_layout, {[styles.mobile]: isMobile})}>
|
||||
<antd.Layout style={theme} id="primaryLayout" className={classnames(styles.primary_layout, {[styles.mobile]: isMobile})}>
|
||||
<Sider {...SiderProps} />
|
||||
|
||||
<div className={styles.primary_layout_container}>
|
||||
|
@ -12,16 +12,24 @@
|
||||
}
|
||||
|
||||
.primary_layout {
|
||||
background-repeat: repeat-x;
|
||||
background-size: cover;
|
||||
background-position-y: center;
|
||||
|
||||
overflow: hidden;
|
||||
background-color: @primary_layout_backgroud;
|
||||
background-color: transparent;
|
||||
margin: auto;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
|
||||
transition: all @__Global_Components_transitions_dur linear;
|
||||
|
||||
&.mobile{
|
||||
>.primary_layout_container {
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-y: overlay;
|
||||
overflow-x: hidden;
|
||||
min-width: unset;
|
||||
}
|
||||
.primary_layout_content{
|
||||
padding: 35px 15px 15px 15px;
|
||||
@ -31,25 +39,40 @@
|
||||
|
||||
// PRIMARY LAYOUT
|
||||
.primary_layout_container {
|
||||
transition: background-color @__Global_layout_transitions-dur linear;
|
||||
background-color: @primary_layout_container_backgroud;
|
||||
border-radius: @primary_layout_container_border-rd;
|
||||
background-color: transparent;
|
||||
transition: all @__Global_Components_transitions_dur linear;
|
||||
|
||||
overflow-x: hidden;
|
||||
margin: 0 0 0 10px;
|
||||
width: 100vw;
|
||||
// overflow-y: overlay;
|
||||
|
||||
width: auto;
|
||||
height: 100vh;
|
||||
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-self: center;
|
||||
float: left;
|
||||
|
||||
max-width: 750px;
|
||||
|
||||
min-width: 570px;
|
||||
|
||||
@media (min-width: @bp-medium) {
|
||||
min-width: 650px;
|
||||
}
|
||||
@media (min-width: @bp-large) {
|
||||
min-width: 850px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.primary_layout_content {
|
||||
vertical-align: middle;
|
||||
width: 100%;
|
||||
float: right;
|
||||
padding: @primary_layout_content_padding;
|
||||
transition: all @__Global_layout_transitions-dur ease;
|
||||
|
||||
@media (max-width: @bp-medium) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,67 @@
|
||||
export default ({ children }) => {
|
||||
return children
|
||||
import React from 'react'
|
||||
import store from 'store'
|
||||
|
||||
import {
|
||||
MyLayout,
|
||||
PageTransition,
|
||||
} from 'components'
|
||||
import { enquireScreen, unenquireScreen } from 'enquire-js'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
import styles from './PrimaryLayout.less'
|
||||
|
||||
const { Content } = antd.Layout
|
||||
|
||||
export default class PublicLayout extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
window.PrimaryComponent = this
|
||||
this.state = {
|
||||
isMobile: false,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.enquireHandler = enquireScreen(mobile => {
|
||||
const { isMobile } = this.state
|
||||
if (isMobile !== mobile) {
|
||||
this.setState({
|
||||
isMobile: mobile,
|
||||
})
|
||||
store.set('mobile_src', mobile)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
unenquireScreen(this.enquireHandler)
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { children } = this.props
|
||||
const { isMobile } = this.state
|
||||
return (
|
||||
<React.Fragment>
|
||||
<antd.Layout id="publicLayout" className={classnames(styles.primary_layout, {[styles.mobile]: isMobile})}>
|
||||
<div className={styles.primary_layout_container}>
|
||||
<PageTransition
|
||||
preset="moveToRightScaleUp"
|
||||
transitionKey={window.location.pathname}
|
||||
>
|
||||
<Content
|
||||
id="publicContent"
|
||||
className={styles.primary_layout_content}
|
||||
>
|
||||
{children}
|
||||
</Content>
|
||||
</PageTransition>
|
||||
</div>
|
||||
</antd.Layout>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* global window */
|
||||
import { router } from 'utils'
|
||||
import store from 'store'
|
||||
import { pathMatchRegexp } from 'utils'
|
||||
import { pathMatchRegexp, queryLayout } from 'utils'
|
||||
import config from 'config'
|
||||
import * as app from 'app'
|
||||
|
||||
@ -42,23 +42,23 @@ export default {
|
||||
},
|
||||
effects: {
|
||||
*query({ payload }, { call, put, select }) {
|
||||
// if (queryLayout(config.layouts, window.location.pathname) == 'public') {
|
||||
// return true
|
||||
// }
|
||||
const validBackup = app.validate.backup()
|
||||
if (app.validate.session() == true) {
|
||||
if (pathMatchRegexp(['/', '/login'], window.location.pathname)) {
|
||||
router.push({ pathname: '/main' })
|
||||
router.push({ pathname: `${config.MainPath}` })
|
||||
}
|
||||
app._app.query()
|
||||
return true
|
||||
} else if (!pathMatchRegexp(['', '/login'], window.location.pathname)) {
|
||||
} else if (!pathMatchRegexp(['', '/login'], window.location.pathname) && queryLayout(config.layouts, window.location.pathname) !== 'public') {
|
||||
if (validBackup == true) {
|
||||
app._app.logout()
|
||||
} else {
|
||||
router.push({ pathname: '/login' })
|
||||
}
|
||||
}
|
||||
if (pathMatchRegexp([''], window.location.pathname)) {
|
||||
router.push({ pathname: '/login' })
|
||||
}
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
|
21
src/pages/debug/index.js
Normal file
21
src/pages/debug/index.js
Normal file
@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
|
||||
export default class Debug extends React.Component{
|
||||
|
||||
render(){
|
||||
return(
|
||||
<>
|
||||
<div>Debug</div><hr/>
|
||||
<button onClick={() => app.notify.fatal('Error test! sike')} >Send Critical error</button>
|
||||
<button onClick={() => {
|
||||
|
||||
|
||||
}}> start storage logs </button>
|
||||
<button onClick={() =>{
|
||||
app.logger.download();
|
||||
}}> Download logs </button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
@ -3,7 +3,9 @@ import * as app from 'app'
|
||||
|
||||
class Index extends PureComponent {
|
||||
render() {
|
||||
app.router.go(`login`)
|
||||
return(
|
||||
<div></div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import styles from './index.less'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
import { RegistrationForm } from './register.js'
|
||||
import { NormalLoginForm } from './login.js'
|
||||
|
@ -94,7 +94,6 @@ export class NormalLoginForm extends React.PureComponent {
|
||||
switch (res) {
|
||||
case '200': {
|
||||
this.anim_transition(300)
|
||||
app.LoginPage.transitionToogle()
|
||||
return
|
||||
}
|
||||
case '400': {
|
||||
|
@ -6,10 +6,10 @@ import styles from './index.less'
|
||||
export default class Main extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.mainWrapper}>
|
||||
<>
|
||||
<PostCreator userData={app.userData()} />
|
||||
<MainFeed auto={true} get="feed" />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,2 @@
|
||||
@import '~themes/index.less';
|
||||
|
||||
.mainWrapper {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import MessageInput from '../messages/MessageInput'
|
||||
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import styles from '../styles.less'
|
||||
import classnames from 'classnames'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import io from 'socket.io-client'
|
||||
import config from 'config'
|
||||
import ReactEmoji from 'react-emoji';
|
||||
@ -19,6 +19,7 @@ export default class Chats extends React.Component{
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
err_tick: 0,
|
||||
socket:null,
|
||||
user:null,
|
||||
conn: false
|
||||
@ -40,7 +41,7 @@ export default class Chats extends React.Component{
|
||||
console.log(prefix, "Connected");
|
||||
const payload = { id: userData.UserID, name: userData.username, avatar: userData.avatar }
|
||||
socket.emit(USER_CONNECTED, payload);
|
||||
this.setState({user: payload, conn: true})
|
||||
this.setState({user: payload, conn: true, err_tick: 0})
|
||||
})
|
||||
}
|
||||
|
||||
@ -51,13 +52,19 @@ export default class Chats extends React.Component{
|
||||
})
|
||||
|
||||
socket.on('reconnecting', () =>{
|
||||
console.log(prefix, 'Trying to reconnect')
|
||||
this.setState({ err_tick: (this.state.err_tick+1) })
|
||||
console.log(prefix, 'Trying to reconnect', this.state.err_tick)
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { socket, user } = this.state
|
||||
if(!user) return <div ><h1>Loading</h1></div>
|
||||
if( this.state.err_tick > 2) return <antd.Result
|
||||
status="500"
|
||||
title="You're offline"
|
||||
subTitle="It seems that you are disconnected and could not connect to the server."
|
||||
/>
|
||||
if(!user) return <div style={{ backgroundColor: '#fff', borderRadius: '10px', padding: '20px', marginTop: '50px' }}><h1> <Icons.LoadingOutlined spin /> Connecting to server...</h1><antd.Skeleton active /></div>
|
||||
return <ChatContainer socket={socket} user={user} />
|
||||
|
||||
}
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import { pathMatchRegexp } from 'utils'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
export default class Indexer_Post extends React.Component {
|
||||
constructor(props) {
|
||||
@ -20,7 +20,7 @@ export default class Indexer_Post extends React.Component {
|
||||
if (err) {
|
||||
return false
|
||||
}
|
||||
app.OverlaySwap.openPost(res)
|
||||
app.SwapMode.openPost(res)
|
||||
}, payload)
|
||||
}
|
||||
|
||||
|
9
src/pages/publics/index.js
Normal file
9
src/pages/publics/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
|
||||
export default class TestPublic extends React.Component{
|
||||
render(){
|
||||
return(
|
||||
<div>Test your Publics!</div>
|
||||
)
|
||||
}
|
||||
}
|
13
src/pages/publics/style_design.js
Normal file
13
src/pages/publics/style_design.js
Normal file
@ -0,0 +1,13 @@
|
||||
import React from 'react'
|
||||
import config from 'config'
|
||||
|
||||
|
||||
export default class PAGE_PUBLIC extends React.Component{
|
||||
render(){
|
||||
return(
|
||||
<div>
|
||||
<img src={config.DarkFullLogoPath} /> <h1>Style Design</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import { MainFeed } from 'components'
|
||||
import styles from './index.less'
|
||||
|
||||
|
@ -1,9 +1,32 @@
|
||||
import React from 'react'
|
||||
import { App_about } from 'components'
|
||||
import l from 'globals/links'
|
||||
import * as Icons from 'components/Icons'
|
||||
import * as antd from 'antd'
|
||||
|
||||
|
||||
|
||||
export default class AppAbout extends React.Component {
|
||||
render() {
|
||||
return <App_about />
|
||||
return <>
|
||||
<App_about />
|
||||
<antd.Card>
|
||||
<div>
|
||||
<h4>🎉✨ It's completely free and open source !</h4>
|
||||
<h5>It is an impressive amount of work and effort, help us to continue offering quality services, you can support us from our patreon campaign.</h5>
|
||||
<a href={l.patreon}><Icons.Patreon/> Support us with Patreon!</a>
|
||||
</div>
|
||||
<antd.Divider dashed />
|
||||
<div>
|
||||
<h4>👨💻 You are developer? You can help us by joining our team!</h4>
|
||||
<a href={l.gitlab}><Icons.Gitlab />Official Repository</a><br />
|
||||
<a href={l.github}><Icons.GitHub />Mirror Repository</a><br />
|
||||
<a href={l.trellojoin}><Icons.Trello />Join our Trello</a>
|
||||
</div>
|
||||
</antd.Card>
|
||||
|
||||
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,8 @@ import { List, Switch, Button, notification, InputNumber } from 'antd'
|
||||
import { ListSettings } from '../../../../globals/settings.js'
|
||||
import { ControlBar } from 'app'
|
||||
import * as app from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { CustomIcons } from 'components'
|
||||
|
||||
class Base extends Component {
|
||||
constructor(props) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
|
||||
export default class Earnings extends React.Component {
|
||||
|
9
src/pages/settings/components/help/index.js
Normal file
9
src/pages/settings/components/help/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
|
||||
export default class Help extends React.Component{
|
||||
render(){
|
||||
return <>
|
||||
|
||||
</>
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import styles from './index.less'
|
||||
|
||||
export default class NotificationView extends React.Component {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import * as app from 'app'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import * as antd from 'antd'
|
||||
import styles from './index.less'
|
||||
|
||||
|
230
src/pages/settings/components/theme/index.js
Normal file
230
src/pages/settings/components/theme/index.js
Normal file
@ -0,0 +1,230 @@
|
||||
import React from 'react'
|
||||
import * as Feather from 'feather-reactjs'
|
||||
import * as app from 'app'
|
||||
import * as antd from 'antd'
|
||||
|
||||
import { SketchPicker } from 'react-color';
|
||||
|
||||
import ColorThief from 'colorthief/dist/color-thief'
|
||||
var colorThief = new ColorThief();
|
||||
|
||||
|
||||
class BackgroundColor extends React.Component{
|
||||
state = {
|
||||
selected: "#fff"
|
||||
}
|
||||
sendChanges(){
|
||||
this.props.changeColor(this.state.selected)
|
||||
}
|
||||
selectColor = (color) =>{
|
||||
this.setState({selected: color.hex})
|
||||
}
|
||||
render(){
|
||||
return <>
|
||||
<SketchPicker
|
||||
color={this.state.selected}
|
||||
onChangeComplete={this.selectColor}
|
||||
/>
|
||||
<antd.Button onClick={() => this.sendChanges()}> Change </antd.Button>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
class BackgroundImage extends React.Component{
|
||||
state = {
|
||||
results: []
|
||||
}
|
||||
|
||||
search(key){
|
||||
if (!key) return false
|
||||
app.api_unsplash.search(key, (res) =>{
|
||||
console.log(res)
|
||||
this.setState({ results: res })
|
||||
})
|
||||
}
|
||||
returnString(url){
|
||||
this.props.selectImg(`url(${url})`)
|
||||
}
|
||||
render(){
|
||||
return (
|
||||
<>
|
||||
<h3> <Feather.Image /> Upload </h3>
|
||||
<antd.Divider type="horizontal" dashed />
|
||||
|
||||
<h3> Unsplash </h3>
|
||||
<antd.Input.Search onSearch={value => this.search(value)} />
|
||||
<antd.List itemLayout="vertical" dataSource={this.state.results} renderItem={item => ( <antd.List.Item> <img onClick={() => this.returnString(item.urls.full)} src={item.urls.small} /> </antd.List.Item>) }/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default class ThemeSettings extends React.PureComponent{
|
||||
state = {
|
||||
helper_visible: false,
|
||||
helper_fragment: null,
|
||||
style: [],
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
this.decodeData()
|
||||
}
|
||||
|
||||
decodeData(){
|
||||
const storaged = app.app_theme.getString()
|
||||
try {
|
||||
if (storaged) {
|
||||
this.decode(storaged, (res) => {
|
||||
this.setState({ style: res })
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
encode(data, callback){
|
||||
if (!data) return false
|
||||
try {
|
||||
let mix = []
|
||||
const obj = Object.entries(data)
|
||||
obj.forEach((e) => {
|
||||
mix.push({key: e[0], value: e[1]})
|
||||
})
|
||||
return callback(JSON.stringify(mix))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
decode(data, callback){
|
||||
if (!data) return false
|
||||
try {
|
||||
const scheme = JSON.parse(data)
|
||||
let mix = {};
|
||||
scheme.forEach((e)=>{
|
||||
mix[e.key] = e.value
|
||||
})
|
||||
return callback(mix)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
handleChanges(key, value){
|
||||
let { style } = this.state
|
||||
try {
|
||||
switch (key) {
|
||||
case "backgroundImage":{
|
||||
if(style.backgroundColor){
|
||||
this.handleRemove("backgroudColor")
|
||||
}
|
||||
style[key] = value
|
||||
this.encode(style, (res) => {
|
||||
app.app_theme.set(res)
|
||||
this.setPredominantColor(value)
|
||||
})
|
||||
return true
|
||||
}
|
||||
case "backgroundColor":{
|
||||
if(style.backgroundImage){
|
||||
this.handleRemove("backgroundImage")
|
||||
}
|
||||
style[key] = value
|
||||
this.encode(style, (res) => {
|
||||
app.app_theme.set(res)
|
||||
this.handleChanges("predominantColor", value)
|
||||
})
|
||||
}
|
||||
default:{
|
||||
style[key] = value
|
||||
this.encode(style, (res) => {
|
||||
app.app_theme.set(res)
|
||||
})
|
||||
}
|
||||
}
|
||||
this.decodeData()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
resetStyles(){
|
||||
app.app_theme.set([])
|
||||
}
|
||||
|
||||
handleRemove(key){
|
||||
try {
|
||||
const storaged = JSON.parse(app.app_theme.getString())
|
||||
let mix = {};
|
||||
storaged.forEach((e)=>{
|
||||
return e.key !== key? mix[e.key] = e.value : null
|
||||
})
|
||||
console.log(mix)
|
||||
this.encode(mix, (res)=> {
|
||||
app.app_theme.set(res)
|
||||
this.decodeData()
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setPredominantColor(furl){
|
||||
const _this = this
|
||||
const img = new Image();
|
||||
const url = ((furl.replace("url", "")).substring(1)).slice(0, -1);
|
||||
|
||||
img.crossOrigin = 'Anonymous';
|
||||
img.src = url
|
||||
|
||||
img.addEventListener('load', function() {
|
||||
const color = `rgb(${colorThief.getColor(img)})`
|
||||
_this.handleChanges("predominantColor", color)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
helper = {
|
||||
open: (e) => {
|
||||
this.setState({ helper_visible: true, helper_fragment: e })
|
||||
},
|
||||
close: () => {
|
||||
this.setState({ helper_visible: false, helper_fragment: null })
|
||||
},
|
||||
backgroundImage: () => {
|
||||
this.helper.open(<BackgroundImage selectImg={(i) => this.handleChanges("backgroundImage", i)} />)
|
||||
},
|
||||
backgroundColor: () => {
|
||||
this.helper.open(<BackgroundColor changeColor={(i) => this.handleChanges("backgroundColor", i)} />)
|
||||
}
|
||||
}
|
||||
render(){
|
||||
return(
|
||||
<div>
|
||||
<h2><Feather.Layers/> Theme</h2>
|
||||
<div>
|
||||
<button onClick={() => this.helper.backgroundImage()}> Background Image</button>
|
||||
<button onClick={() => this.helper.backgroundColor()}> Background Color </button>
|
||||
<button onClick={() => this.resetStyles()}> Reset Style </button>
|
||||
</div>
|
||||
<antd.Drawer
|
||||
title="Theme Settings"
|
||||
placement="right"
|
||||
width="500"
|
||||
closable={true}
|
||||
onClose={this.helper.close}
|
||||
visible={this.state.helper_visible}
|
||||
>
|
||||
<React.Fragment>
|
||||
{this.state.helper_fragment}
|
||||
</React.Fragment>
|
||||
</antd.Drawer>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
0
src/pages/settings/components/theme/index.less
Normal file
0
src/pages/settings/components/theme/index.less
Normal file
@ -1,6 +1,8 @@
|
||||
import React from 'react'
|
||||
import { Menu } from 'antd'
|
||||
import * as Icons from '@ant-design/icons'
|
||||
import * as Icons from 'components/Icons'
|
||||
import * as Feather from 'feather-reactjs'
|
||||
|
||||
import styles from './style.less'
|
||||
|
||||
import NotificationView from './components/notification/index.js'
|
||||
@ -9,6 +11,7 @@ import Earnings from './components/earnings/index.js'
|
||||
|
||||
import Base from './components/base.js'
|
||||
import AppAbout from './components/about.js'
|
||||
import Theme from './components/theme'
|
||||
|
||||
const { Item } = Menu
|
||||
const menuMap = {
|
||||
@ -17,6 +20,11 @@ const menuMap = {
|
||||
<Icons.ControlOutlined /> General
|
||||
</span>
|
||||
),
|
||||
theme: (
|
||||
<span>
|
||||
<Feather.Layers /> Theme
|
||||
</span>
|
||||
),
|
||||
sync: (
|
||||
<span>
|
||||
<Icons.SyncOutlined /> Sync™
|
||||
@ -24,12 +32,12 @@ const menuMap = {
|
||||
),
|
||||
security: (
|
||||
<span>
|
||||
<Icons.SafetyCertificateOutlined /> Security & Privacity
|
||||
<Feather.Lock /> Security & Privacity
|
||||
</span>
|
||||
),
|
||||
notification: (
|
||||
<span>
|
||||
<Icons.MailOutlined /> Notification
|
||||
<Feather.Bell /> Notification
|
||||
</span>
|
||||
),
|
||||
earnings: (
|
||||
@ -37,9 +45,14 @@ const menuMap = {
|
||||
<Icons.DollarCircleOutlined /> Earnings
|
||||
</span>
|
||||
),
|
||||
help: (
|
||||
<span>
|
||||
<Icons.LifeBuoy /> Help
|
||||
</span>
|
||||
),
|
||||
about: (
|
||||
<span>
|
||||
<Icons.ContainerOutlined /> About
|
||||
<Feather.Info /> About
|
||||
</span>
|
||||
),
|
||||
}
|
||||
@ -71,6 +84,8 @@ class GeneralSettings extends React.Component {
|
||||
return <Base />
|
||||
case 'security':
|
||||
return <SecurityView />
|
||||
case 'theme':
|
||||
return <Theme />
|
||||
case 'notification':
|
||||
return <NotificationView />
|
||||
case 'about':
|
||||
@ -89,7 +104,7 @@ class GeneralSettings extends React.Component {
|
||||
<div className={styles.main}>
|
||||
<div className={styles.leftMenu}>
|
||||
<h2>
|
||||
<Icons.SettingOutlined /> Settings{' '}
|
||||
<Icons.SettingOutlined /> Settings
|
||||
</h2>
|
||||
<Menu
|
||||
mode="inline"
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
.leftMenu {
|
||||
width: 224px;
|
||||
|
||||
:global {
|
||||
.ant-menu-inline {
|
||||
color: @__Global_layout_color;
|
||||
|
@ -8,6 +8,8 @@
|
||||
@import './components/PostCard.less';
|
||||
|
||||
|
||||
@__Global_backgroud_image: "";
|
||||
|
||||
@__Global_general_font_family: "Poppins", sans-serif;
|
||||
@__Global_texted_font: "Manrope", sans-serif;
|
||||
@__Global_alternative_font: "Netflix Sans";
|
||||
@ -20,10 +22,14 @@
|
||||
|
||||
|
||||
@__Global_SwapAnimDuration: 170ms;
|
||||
@__Global_backdrop_backgroud: rgba(158, 158, 158, 0.5);
|
||||
|
||||
@transition-ease-in: all 0.3s ease-out;
|
||||
@transition-ease-out: all 0.3s ease-out;
|
||||
@ease-in: ease-in;
|
||||
@transition-ease-inout: all 150ms ease-in-out;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Overlay_wrapper_hidden_width: 22vw;
|
||||
@ -75,8 +81,11 @@ body {
|
||||
line-height: @base-line-height;
|
||||
|
||||
font-family: @__Global_texted_font;
|
||||
}
|
||||
|
||||
background-color: @primary_layout_backgroud;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: @bp-small){
|
||||
::-webkit-scrollbar{
|
||||
@ -85,7 +94,7 @@ body {
|
||||
}
|
||||
|
||||
@media (min-width: @bp-medium) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: @bp-large) {
|
||||
@ -93,15 +102,11 @@ body {
|
||||
}
|
||||
|
||||
@media (min-width: @bp-xlarge) {
|
||||
body{
|
||||
zoom: 1.4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: @bp-xxlarge) {
|
||||
body{
|
||||
zoom: 1.6;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
@import '~themes/index.less';
|
||||
|
||||
// .left_sider*
|
||||
@left_sider_backgroud: #F8F6F8;
|
||||
@left_sider_color: #fff;
|
||||
|
||||
@left_sider_color: #333;
|
||||
@left_sider_sizeIcons: 19px;
|
||||
@left_sider_menu__onhover_backgroud: rgb(80, 80, 80);
|
||||
@left_sider_menu__onhover_color: #fff;
|
||||
@left_sider_menu__onhover_color: rgb(80, 80, 80);
|
@ -5,5 +5,5 @@
|
||||
@primary_layout_container_backgroud: @__Global_layout_backgroud;
|
||||
@primary_layout_container_border-rd: @__Global_layout_border-rd;
|
||||
|
||||
@primary_layout_content_padding: 35px 25px 15px 40px;
|
||||
@primary_layout_content_padding: 25px;
|
||||
|
||||
|
@ -247,9 +247,11 @@ export const _app = {
|
||||
app.notify.success('Authorised, please wait...')
|
||||
const resourceLoad = localStorage.getItem('resource_bundle')
|
||||
if (!resourceLoad) {
|
||||
localStorage.setItem('resource_bundle', 'light_ng')
|
||||
localStorage.setItem('resource_bundle', 'comtyng_default')
|
||||
}
|
||||
app.router.push('main')
|
||||
setTimeout(() => {
|
||||
app.router.push('main')
|
||||
}, 420)
|
||||
},
|
||||
query: () => {
|
||||
const validBackup = app.validate.backup()
|
||||
|
32
test/login.test.js
Normal file
32
test/login.test.js
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
import puppeteer from 'puppeteer'
|
||||
|
||||
describe('Login', () => {
|
||||
let browser
|
||||
let page
|
||||
|
||||
beforeAll(async () => {
|
||||
browser = await puppeteer.launch({ args: ['--no-sandbox'] })
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
page = await browser.newPage()
|
||||
await page.goto('http://localhost:8000/en/login', {
|
||||
waitUntil: 'networkidle2',
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => page.close())
|
||||
|
||||
it('should login with failure', async () => {
|
||||
await page.waitFor(selector => !!document.querySelector('#username'), {
|
||||
timeout: 3000,
|
||||
})
|
||||
await page.type('#username', 'wrong_user')
|
||||
await page.type('#password', 'wrong_password')
|
||||
await page.click('button[type="button"]')
|
||||
await page.waitForSelector('.anticon-close-circle') // should display error
|
||||
})
|
||||
|
||||
afterAll(() => browser.close())
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user