mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 19:14:16 +00:00
*update: contextual menu
*upadate: theme handlers & darkmodes *added: window controllers api
This commit is contained in:
parent
a863864644
commit
c75f0744c2
@ -1,5 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
app_config: {
|
app_config: {
|
||||||
|
id: "comty",
|
||||||
siteName: 'Comty',
|
siteName: 'Comty',
|
||||||
copyright: 'RageStudio©',
|
copyright: 'RageStudio©',
|
||||||
MainPath: '/',
|
MainPath: '/',
|
||||||
@ -12,6 +13,7 @@ module.exports = {
|
|||||||
api_prefix: 'ycorejs_apiv3',
|
api_prefix: 'ycorejs_apiv3',
|
||||||
app_settings_storage: 'app_settings',
|
app_settings_storage: 'app_settings',
|
||||||
endpoint_global: 'https://comty.pw',
|
endpoint_global: 'https://comty.pw',
|
||||||
|
proxy_local: 'http://localhost:8000',
|
||||||
|
|
||||||
session_token_storage: 'cid',
|
session_token_storage: 'cid',
|
||||||
session_data_storage: 'data',
|
session_data_storage: 'data',
|
||||||
|
14
globals/contextMenu.js
Normal file
14
globals/contextMenu.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import * as Icons from 'components/Icons'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
key: "inspect_element",
|
||||||
|
title: "Inspect",
|
||||||
|
icon: <Icons.Command />,
|
||||||
|
params: {
|
||||||
|
onClick: (e) => {
|
||||||
|
window.inspectElement(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -20,8 +20,9 @@ const packagejson = require('../package.json')
|
|||||||
const is = require('electron-is')
|
const is = require('electron-is')
|
||||||
const waitOn = require('wait-on');
|
const waitOn = require('wait-on');
|
||||||
const { getDoNotDisturb } = require('electron-notification-state');
|
const { getDoNotDisturb } = require('electron-notification-state');
|
||||||
|
const { app_config } = require("../config");
|
||||||
|
|
||||||
let app_path = is.dev()? 'http://127.0.0.1:8000/' : `file://${path.join(__dirname, '..', 'renderer')}/index.html`;
|
let app_path = is.dev()? app_config.proxy_local : `file://${path.join(__dirname, '..', 'renderer')}/index.html`;
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
let tray;
|
let tray;
|
||||||
let watcher;
|
let watcher;
|
||||||
@ -272,6 +273,5 @@ ipcMain.handle('contextualMenu', (event, payload) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('inspectElement', (event, payload) => {
|
ipcMain.handle('inspectElement', (event, payload) => {
|
||||||
log.log(payload)
|
|
||||||
mainWindow.inspectElement(payload.x, payload.y)
|
mainWindow.inspectElement(payload.x, payload.y)
|
||||||
})
|
})
|
@ -51,6 +51,7 @@
|
|||||||
"electron-updater": "^4.3.4",
|
"electron-updater": "^4.3.4",
|
||||||
"enquire-js": "^0.2.1",
|
"enquire-js": "^0.2.1",
|
||||||
"feather-reactjs": "^2.0.13",
|
"feather-reactjs": "^2.0.13",
|
||||||
|
"html2canvas": "^1.0.0-rc.7",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"less-vars-to-js": "^1.3.0",
|
"less-vars-to-js": "^1.3.0",
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
> div{
|
> div{
|
||||||
|
transition: all 100ms linear;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
@ -26,4 +28,8 @@
|
|||||||
background-color: #e3e3e3;
|
background-color: #e3e3e3;
|
||||||
color: rgba(36, 36, 36, 0.7);
|
color: rgba(36, 36, 36, 0.7);
|
||||||
}
|
}
|
||||||
|
> div:active{
|
||||||
|
transform: scale(0.98);
|
||||||
|
filter: brightness(110%);
|
||||||
|
}
|
||||||
}
|
}
|
@ -18,27 +18,26 @@ export default class ContextMenu extends React.Component<ContextMenu_props>{
|
|||||||
this.setWrapperRef = this.setWrapperRef.bind(this)
|
this.setWrapperRef = this.setWrapperRef.bind(this)
|
||||||
this.handleClickOutside = this.handleClickOutside.bind(this)
|
this.handleClickOutside = this.handleClickOutside.bind(this)
|
||||||
|
|
||||||
this.eventListener = document.addEventListener('click', this.handleClickOutside, false)
|
this.eventListener = () => {
|
||||||
|
document.addEventListener('click', this.handleClickOutside, false)
|
||||||
|
this.listening = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setWrapperRef(node){
|
setWrapperRef(node){
|
||||||
this.wrapperRef = node
|
this.wrapperRef = node
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClickOutside(event) {
|
handleClickOutside(event) {
|
||||||
if ( this.props.visible || this.wrapperRef && !this.wrapperRef.contains(event.target)) {
|
if ( this.props.visible && this.wrapperRef && !this.wrapperRef.contains(event.target)) {
|
||||||
window.contextMenu.toogle()
|
|
||||||
this.listening = false
|
this.listening = false
|
||||||
|
window.contextMenu.toogle()
|
||||||
document.removeEventListener('click', this.eventListener, false)
|
document.removeEventListener('click', this.eventListener, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(){
|
componentDidUpdate(){
|
||||||
if (!this.listening) {
|
!this.listening ? this.eventListener() : null
|
||||||
this.listening = true
|
|
||||||
this.eventListener
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
|
@ -9,10 +9,8 @@ import classnames from 'classnames'
|
|||||||
|
|
||||||
import settings from 'core/libs/settings'
|
import settings from 'core/libs/settings'
|
||||||
import { router } from 'core/cores'
|
import { router } from 'core/cores'
|
||||||
import { notify } from 'core/libs/interface'
|
|
||||||
import LikeBtn from './components/like'
|
import LikeBtn from './components/like'
|
||||||
import { connect } from 'umi'
|
import { connect } from 'umi'
|
||||||
import config from 'config'
|
|
||||||
|
|
||||||
const { Meta } = antd.Card
|
const { Meta } = antd.Card
|
||||||
|
|
||||||
@ -33,6 +31,44 @@ const defaultPayload = {
|
|||||||
ReportIgnore: false,
|
ReportIgnore: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const contextMenuPost = [
|
||||||
|
{
|
||||||
|
key: "inspect_element",
|
||||||
|
title: "Copy URL",
|
||||||
|
icon: <Icons.Clipboard />,
|
||||||
|
params: {
|
||||||
|
onClick: (e) => {
|
||||||
|
core.writeToClipboard(core.generatePostURI(e.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "screenshot",
|
||||||
|
title: "Save screenshot",
|
||||||
|
icon: <Icons.Aperture />,
|
||||||
|
params: {
|
||||||
|
itemProps: {
|
||||||
|
style: { color: "#40a9ff" }
|
||||||
|
},
|
||||||
|
onClick: (e) => {
|
||||||
|
core.createScreenshotFromElement(document.getElementById(e.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "require_test",
|
||||||
|
title: "Require Test => DEV",
|
||||||
|
icon: <Icons.Cloud />,
|
||||||
|
params: {
|
||||||
|
onClick: (e) => {
|
||||||
|
console.log('Heeeey you developeeer')
|
||||||
|
},
|
||||||
|
keepOnClick: true,
|
||||||
|
require: "dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
@connect(({ app }) => ({ app }))
|
@connect(({ app }) => ({ app }))
|
||||||
export default class PostCard extends React.Component {
|
export default class PostCard extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
@ -47,13 +83,6 @@ export default class PostCard extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
generatePostURI(id){
|
|
||||||
if(config.app_config.endpoint_global && id){
|
|
||||||
return `${config.app_config.endpoint_global}/post/${id}`
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
goElementById(id){
|
goElementById(id){
|
||||||
document.getElementById(id).scrollIntoView({
|
document.getElementById(id).scrollIntoView({
|
||||||
behavior: "smooth",
|
behavior: "smooth",
|
||||||
@ -66,19 +95,6 @@ export default class PostCard extends React.Component {
|
|||||||
this.setState({ visibleMoreMenu: !this.state.visibleMoreMenu })
|
this.setState({ visibleMoreMenu: !this.state.visibleMoreMenu })
|
||||||
}
|
}
|
||||||
|
|
||||||
handleActions(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
writeToClipboard(text){
|
|
||||||
navigator.clipboard.writeText(text)
|
|
||||||
.then(() => {
|
|
||||||
notify.info('Copy to clipboard')
|
|
||||||
}, () => {
|
|
||||||
/* failure */
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
renderReportedPost(){
|
renderReportedPost(){
|
||||||
if(this.state.ReportIgnore) return null
|
if(this.state.ReportIgnore) return null
|
||||||
return (
|
return (
|
||||||
@ -160,6 +176,8 @@ export default class PostCard extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
//
|
||||||
|
|
||||||
const actions = [
|
const actions = [
|
||||||
<LikeBtn count={this.state.payload.post_likes} liked={core.booleanFix(this.state.payload.is_liked)} />,
|
<LikeBtn count={this.state.payload.post_likes} liked={core.booleanFix(this.state.payload.is_liked)} />,
|
||||||
<Icons.Share2 />,
|
<Icons.Share2 />,
|
||||||
@ -169,12 +187,12 @@ export default class PostCard extends React.Component {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.post_card_wrapper}>
|
<div key={this.state.payload.id} id={this.state.payload.id} className={styles.post_card_wrapper}>
|
||||||
<antd.Card
|
<antd.Card
|
||||||
className={settings("post_hidebar") ? null : styles.showMode}
|
className={settings("post_hidebar") ? null : styles.showMode}
|
||||||
onDoubleClick={() => null}
|
onDoubleClick={() => null}
|
||||||
onClick={() => this.goElementById(this.state.payload.id)}
|
onClick={() => this.goElementById(this.state.payload.id)}
|
||||||
onContextMenu={() => this.writeToClipboard(this.generatePostURI(this.state.payload.id))}
|
onContextMenu={(e) => { window.contextMenu.open({ xPos: e.clientX, yPos: e.clientY, fragment: window.contextMenu.generate(contextMenuPost, this.state.payload) }) }}
|
||||||
actions={actions}
|
actions={actions}
|
||||||
hoverable
|
hoverable
|
||||||
>
|
>
|
||||||
|
@ -6,14 +6,14 @@ import { i18n, app_config } from 'config';
|
|||||||
import * as errorHandlers from 'core/libs/errorhandler'
|
import * as errorHandlers from 'core/libs/errorhandler'
|
||||||
import platform from 'platform'
|
import platform from 'platform'
|
||||||
import request from 'request'
|
import request from 'request'
|
||||||
|
import html2canvas from 'html2canvas'
|
||||||
|
|
||||||
const { pathToRegexp } = require('path-to-regexp');
|
const { pathToRegexp } = require('path-to-regexp');
|
||||||
|
|
||||||
export const languages = i18n ? i18n.languages.map(item => item.key) : [];
|
export const languages = i18n ? i18n.languages.map(item => item.key) : [];
|
||||||
export const defaultLanguage = i18n ? i18n.defaultLanguage : '';
|
export const defaultLanguage = i18n ? i18n.defaultLanguage : '';
|
||||||
|
|
||||||
import './libs'
|
import * as libs from './libs'
|
||||||
import './cores'
|
|
||||||
|
|
||||||
export const package_json = require('../../package.json');
|
export const package_json = require('../../package.json');
|
||||||
export const UUAID = `${package_json.name}==${package_json.UUID}`;
|
export const UUAID = `${package_json.name}==${package_json.UUID}`;
|
||||||
@ -29,6 +29,35 @@ export const app_info = {
|
|||||||
layout: platform.layout
|
layout: platform.layout
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function createScreenshotFromElement(element){
|
||||||
|
if (!element) return false
|
||||||
|
html2canvas(element, {
|
||||||
|
useCORS: true,
|
||||||
|
proxy: app_config.proxy_local,
|
||||||
|
scale: 4,
|
||||||
|
backgroundColor: "transparent"
|
||||||
|
}).then(canvas => {
|
||||||
|
downloadEncodedURI({ data: canvas.toDataURL() })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function generatePostURI(id){
|
||||||
|
if(app_config.endpoint_global && id){
|
||||||
|
return `${app_config.endpoint_global}/post/${id}`
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeToClipboard(text){
|
||||||
|
navigator.clipboard.writeText(text)
|
||||||
|
.then(() => {
|
||||||
|
libs.Interface.notify.info('Copy to clipboard')
|
||||||
|
}, () => {
|
||||||
|
/* failure */
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// [Experimental], not in use
|
// [Experimental], not in use
|
||||||
export function getGlobals(params, callback) {
|
export function getGlobals(params, callback) {
|
||||||
if (!params || !params.server) return false
|
if (!params || !params.server) return false
|
||||||
@ -79,12 +108,32 @@ export function urlToBase64(url, callback){
|
|||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function b64toBlob(b64Data, contentType='', sliceSize=512){
|
||||||
|
const byteCharacters = atob(b64Data);
|
||||||
|
const byteArrays = [];
|
||||||
|
|
||||||
|
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
|
||||||
|
const slice = byteCharacters.slice(offset, offset + sliceSize);
|
||||||
|
|
||||||
|
const byteNumbers = new Array(slice.length);
|
||||||
|
for (let i = 0; i < slice.length; i++) {
|
||||||
|
byteNumbers[i] = slice.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const byteArray = new Uint8Array(byteNumbers);
|
||||||
|
byteArrays.push(byteArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = new Blob(byteArrays, {type: contentType});
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a download with encoded uri
|
* Generate a download with encoded uri
|
||||||
*
|
*
|
||||||
* @param {object} payload - Generation Data
|
* @param {object} payload - Generation Data
|
||||||
*/
|
*/
|
||||||
export function downloadEncodedURI(payload){
|
export function downloadDecodedURI(payload){
|
||||||
if(!payload) return false
|
if(!payload) return false
|
||||||
let { data, type, charset, filename } = payload
|
let { data, type, charset, filename } = payload
|
||||||
/**
|
/**
|
||||||
@ -94,7 +143,7 @@ export function downloadEncodedURI(payload){
|
|||||||
if (!data || !type) return false
|
if (!data || !type) return false
|
||||||
try {
|
try {
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
filename = `export_${time.now()}.${type.split("/")[1]}`
|
filename = `${app_config.id}_${time.now()}.${type.split("/")[1]}`
|
||||||
}
|
}
|
||||||
let tmp = document.createElement('a')
|
let tmp = document.createElement('a')
|
||||||
tmp.href = `data:${type};charset=${charset},${encodeURIComponent(data)}`
|
tmp.href = `data:${type};charset=${charset},${encodeURIComponent(data)}`
|
||||||
@ -105,6 +154,26 @@ export function downloadEncodedURI(payload){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function downloadEncodedURI(payload){
|
||||||
|
if(!payload) return false
|
||||||
|
let { data, filename } = payload
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} payload - Generation Data
|
||||||
|
*/
|
||||||
|
if (!data) return false
|
||||||
|
try {
|
||||||
|
if (!filename) {
|
||||||
|
filename = `${app_config.id}_${time.now()}.${data.split("/")[1].split(";")[0]}`
|
||||||
|
}
|
||||||
|
let tmp = document.createElement('a')
|
||||||
|
tmp.href = data
|
||||||
|
tmp.download= filename
|
||||||
|
tmp.click()
|
||||||
|
} catch (error) {
|
||||||
|
errorHandlers.onError.internal_proccess(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Return the last object from array
|
* Return the last object from array
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import * as antd from 'antd'
|
import * as antd from 'antd'
|
||||||
import * as Icons from 'components/Icons'
|
import * as Icons from 'components/Icons'
|
||||||
import { downloadEncodedURI } from 'core'
|
import { downloadDecodedURI } from 'core'
|
||||||
|
|
||||||
export interface exportData_props {
|
export interface exportData_props {
|
||||||
data: string;
|
data: string;
|
||||||
@ -25,7 +25,7 @@ const exportData_render = (props: exportData_props) => {
|
|||||||
antd.Modal.confirm({
|
antd.Modal.confirm({
|
||||||
title: <div><Icons.Code /> Your export <antd.Tag> {`${props.type.split("/")[1]}`} </antd.Tag></div>,
|
title: <div><Icons.Code /> Your export <antd.Tag> {`${props.type.split("/")[1]}`} </antd.Tag></div>,
|
||||||
icon: null,
|
icon: null,
|
||||||
onOk: () => downloadEncodedURI({data: props.data, type: props.type}),
|
onOk: () => downloadDecodedURI({data: props.data, type: props.type}),
|
||||||
okText: <><Icons.Download />Download as File</> ,
|
okText: <><Icons.Download />Download as File</> ,
|
||||||
cancelText: "Done",
|
cancelText: "Done",
|
||||||
content: exportCodeRender(props.data),
|
content: exportCodeRender(props.data),
|
||||||
|
@ -13,22 +13,12 @@ import classnames from 'classnames'
|
|||||||
import { app_config } from 'config'
|
import { app_config } from 'config'
|
||||||
import { theme } from 'core/libs/style'
|
import { theme } from 'core/libs/style'
|
||||||
import * as antd from 'antd'
|
import * as antd from 'antd'
|
||||||
import * as Icons from 'components/Icons'
|
import contextMenuList from 'globals/contextMenu'
|
||||||
|
|
||||||
import styles from './PrimaryLayout.less'
|
import styles from './PrimaryLayout.less'
|
||||||
|
|
||||||
const contextMenuList = [
|
|
||||||
{
|
|
||||||
key: "inspect_element",
|
|
||||||
title: "Inspect",
|
|
||||||
icon: <Icons.Command />
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const { Content } = antd.Layout
|
const { Content } = antd.Layout
|
||||||
const { Sider, Overlay, ContextMenu } = AppLayout
|
const { Sider, Overlay, ContextMenu } = AppLayout
|
||||||
const isActive = (key) => { return key? key.active : false }
|
const isActive = (key) => { return key? key.active : false }
|
||||||
const currentTheme = theme.get()
|
|
||||||
|
|
||||||
@withRouter
|
@withRouter
|
||||||
@connect(({ app, loading }) => ({ app, loading }))
|
@connect(({ app, loading }) => ({ app, loading }))
|
||||||
@ -39,54 +29,91 @@ class PrimaryLayout extends React.Component {
|
|||||||
collapsed: app_config.default_collapse_sider ? true : false,
|
collapsed: app_config.default_collapse_sider ? true : false,
|
||||||
isMobile: false
|
isMobile: false
|
||||||
},
|
},
|
||||||
|
this.handleContextMenu = document.getElementById("root").addEventListener("contextmenu", (e) => {
|
||||||
this.handleContextMenu = window.addEventListener("contextmenu", (e) => {
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
window.contextMenu.open({ xPos: e.clientX, yPos: e.clientY, fragment: this.generateContextMenu() })
|
window.contextMenu.open({ xPos: e.clientX, yPos: e.clientY, fragment: window.contextMenu.generate(contextMenuList, e) })
|
||||||
}, false)
|
}, false)
|
||||||
window.DarkMode = isActive(currentTheme["darkmode"])? true : false
|
|
||||||
|
|
||||||
window.contextMenu = this.props.app.contextMenu
|
// include API extensions
|
||||||
window.contextMenu.toogle = () => {
|
window.requireQuery = (require) =>{
|
||||||
|
return new Promise(resolve => {
|
||||||
this.props.dispatch({
|
this.props.dispatch({
|
||||||
type: "app/updateState",
|
type: 'app/isUser',
|
||||||
payload: {contextMenu: {...this.props.app.contextMenu, visible: !this.props.app.contextMenu.visible} }
|
payload: require,
|
||||||
|
callback: (e) => {
|
||||||
|
resolve(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
window.contextMenu.open = (payload) => {
|
window.inspectElement = (e) => this.props.dispatch({
|
||||||
if (!payload) return false
|
|
||||||
const fragment = payload.fragment || null
|
|
||||||
const xPos = payload.xPos || null
|
|
||||||
const yPos = payload.yPos || null
|
|
||||||
this.props.dispatch({
|
|
||||||
type: "app/updateState",
|
|
||||||
payload: {contextMenu: {...this.props.app.contextMenu, xPos, yPos, fragment, visible: true}}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleContextMenuActions = {
|
|
||||||
inspect_element: (e) =>{
|
|
||||||
this.props.dispatch({
|
|
||||||
type: "app/ipcInvoke",
|
type: "app/ipcInvoke",
|
||||||
payload: {
|
payload: {
|
||||||
key: "inspectElement",
|
key: "inspectElement",
|
||||||
payload: { x: e.clientX, y: e.clientY }
|
payload: { x: e.clientX, y: e.clientY }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
window.contextMenu = this.props.app.contextMenu
|
||||||
|
window.contextMenu.open = (payload) => {
|
||||||
|
if (!payload) return false
|
||||||
|
this.props.dispatch({
|
||||||
|
type: "app/updateState",
|
||||||
|
payload: {contextMenu: {
|
||||||
|
...this.props.app.contextMenu,
|
||||||
|
xPos: payload.xPos,
|
||||||
|
yPos: payload.yPos,
|
||||||
|
fragment: payload.fragment,
|
||||||
|
visible: true
|
||||||
|
}}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
generateContextMenu() {
|
window.contextMenu.handle = (e, ...rest) => {
|
||||||
return contextMenuList.map((e) => {
|
if(!e || typeof(e) == 'undefined') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof(e.onClick) !== 'undefined' && e.onClick ? e.onClick(...rest) : null
|
||||||
|
typeof(e.keepOnClick) !== 'undefined' && e.keepOnClick ? null : window.contextMenu.toogle()
|
||||||
|
}
|
||||||
|
|
||||||
|
window.contextMenu.generate = (payload, ...rest) => {
|
||||||
|
if(!payload) return false
|
||||||
|
let tmp = []
|
||||||
|
|
||||||
|
payload.forEach(async(e) => {
|
||||||
|
if (typeof(e.params.require) !== 'undefined') {
|
||||||
|
if(await window.requireQuery(e.params.require)){
|
||||||
|
e.valid = true
|
||||||
|
tmp.push(e)
|
||||||
|
}else{
|
||||||
|
// bruh
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
tmp.push(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return tmp.map((e) => {
|
||||||
return(
|
return(
|
||||||
<div onClick={this.handleContextMenuActions[e.key]} key={e.key}>
|
<div {...e.params.itemProps} onClick={() => window.contextMenu.handle(e.params, ...rest)} key={e.key}>
|
||||||
{e.icon}{e.title}
|
{e.icon}{e.title}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.contextMenu.toogle = () => {
|
||||||
|
this.props.dispatch({
|
||||||
|
type: "app/updateState",
|
||||||
|
payload: {contextMenu: {...this.props.app.contextMenu, visible: !this.props.app.contextMenu.visible} }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.handleContextMenu
|
this.handleContextMenu
|
||||||
|
|
||||||
@ -116,31 +143,13 @@ class PrimaryLayout extends React.Component {
|
|||||||
const { collapsed, isMobile } = this.state
|
const { collapsed, isMobile } = this.state
|
||||||
const { onCollapseChange } = this
|
const { onCollapseChange } = this
|
||||||
const { contextMenu } = app
|
const { contextMenu } = app
|
||||||
const app_theme = isActive(currentTheme["darkmode"])? "dark" : null
|
const currentTheme = theme.get()
|
||||||
|
|
||||||
const breakpoint = {
|
const SiderProps = { isMobile, collapsed, onCollapseChange }
|
||||||
xs: '480px',
|
const OverlayProps = { isMobile }
|
||||||
sm: '576px',
|
|
||||||
md: '768px',
|
|
||||||
lg: '992px',
|
|
||||||
xl: '1200px',
|
|
||||||
xxl: '1600px',
|
|
||||||
}
|
|
||||||
|
|
||||||
const SiderProps = {
|
|
||||||
breakpoint,
|
|
||||||
isMobile,
|
|
||||||
collapsed,
|
|
||||||
onCollapseChange,
|
|
||||||
app_theme
|
|
||||||
}
|
|
||||||
|
|
||||||
const OverlayProps = {
|
|
||||||
breakpoint,
|
|
||||||
isMobile,
|
|
||||||
app_theme
|
|
||||||
}
|
|
||||||
|
|
||||||
|
window.darkMode = isActive(currentTheme["darkmode"])? true : false
|
||||||
|
document.getElementsByTagName("body")[0].setAttribute("class", window.darkMode? "dark" : "light")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@ -164,7 +173,10 @@ class PrimaryLayout extends React.Component {
|
|||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
opacity: currentTheme.backgroundImage.opacity
|
opacity: currentTheme.backgroundImage.opacity
|
||||||
}} /> : null}
|
}} /> : null}
|
||||||
<antd.Layout id="app" className={classnames(styles.app, {[styles.interfaced]: this.props.app.electron, [styles.dark_mode]: isActive(currentTheme['darkmode']) } )}>
|
<antd.Layout id="app" className={classnames(styles.app, {
|
||||||
|
[styles.interfaced]: this.props.app.electron,
|
||||||
|
[styles.dark_mode]: window.darkMode
|
||||||
|
} )}>
|
||||||
<Sider {...SiderProps} />
|
<Sider {...SiderProps} />
|
||||||
<div className={styles.primary_layout_container}>
|
<div className={styles.primary_layout_container}>
|
||||||
<Content
|
<Content
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import React, { Component } from 'react'
|
import React from 'react'
|
||||||
import BaseLayout from './BaseLayout'
|
import BaseLayout from './BaseLayout'
|
||||||
import { withRouter } from 'umi'
|
import { withRouter } from 'umi'
|
||||||
|
const appBody = document.getElementsByTagName("body")[0]
|
||||||
|
|
||||||
@withRouter
|
@withRouter
|
||||||
class Layout extends Component {
|
class Layout extends React.Component {
|
||||||
|
componentDidMount(){
|
||||||
|
const appBody = document.getElementsByTagName("body")[0]
|
||||||
|
appBody.setAttribute("id", "appWrapper")
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
const { children } = this.props
|
const { children } = this.props
|
||||||
return (
|
return (
|
||||||
|
@ -87,12 +87,12 @@ export default {
|
|||||||
},
|
},
|
||||||
effects: {
|
effects: {
|
||||||
*query({ payload }, { call, put, select }) {
|
*query({ payload }, { call, put, select }) {
|
||||||
const service = yield select(state => state.app.service_valid);
|
const service = yield select(state => state.app.service_valid)
|
||||||
const session = yield select(state => state.app.session_valid);
|
const session = yield select(state => state.app.session_valid)
|
||||||
const sessionDataframe = yield select(state => state.app.session_data)
|
const sessionDataframe = yield select(state => state.app.session_data)
|
||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
console.error('❌ Cannot connect with validate session service!');
|
console.error('❌ Cannot connect with validate session service!')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sessionDataframe && session ) {
|
if (!sessionDataframe && session ) {
|
||||||
@ -251,9 +251,7 @@ export default {
|
|||||||
isDev: sessionData.dev,
|
isDev: sessionData.dev,
|
||||||
isPro: sessionData.is_pro
|
isPro: sessionData.is_pro
|
||||||
},
|
},
|
||||||
exp: settings("session_noexpire")
|
exp: Math.floor(Date.now() / 1000) * 120
|
||||||
? 0
|
|
||||||
: Math.floor(Date.now() / 1000) + 60 * 60,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jwt.sign(frame, state.server_key, (err, token) => {
|
jwt.sign(frame, state.server_key, (err, token) => {
|
||||||
@ -285,7 +283,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const session_data = JSON.stringify(JSON.parse(res)["user_data"])
|
const session_data = JSON.stringify(JSON.parse(res)["user_data"])
|
||||||
sessionStorage.setItem(app_config.session_data_storage, btoa(session_data))
|
sessionStorage.setItem(app_config.session_data_storage, btoa(session_data))
|
||||||
state.session_data = session_data
|
location.reload()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
verbosity.error(error)
|
verbosity.error(error)
|
||||||
}
|
}
|
||||||
@ -364,6 +362,8 @@ export default {
|
|||||||
state.session_authframe = null;
|
state.session_authframe = null;
|
||||||
cookie.remove(app_config.session_token_storage)
|
cookie.remove(app_config.session_token_storage)
|
||||||
sessionStorage.clear()
|
sessionStorage.clear()
|
||||||
|
router.push('/')
|
||||||
|
location.reload()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@ import { connect } from 'umi'
|
|||||||
import settings from 'core/libs/settings'
|
import settings from 'core/libs/settings'
|
||||||
import { PostCard, PostCreator } from 'components'
|
import { PostCard, PostCreator } from 'components'
|
||||||
import * as antd from 'antd'
|
import * as antd from 'antd'
|
||||||
|
import styles from './index.less'
|
||||||
|
|
||||||
@connect(({ app }) => ({ app }))
|
@connect(({ app }) => ({ app }))
|
||||||
export default class Explore extends React.Component {
|
export default class Explore extends React.Component {
|
||||||
@ -55,14 +56,12 @@ export default class Explore extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div>
|
<div className={styles.exploreWrapper}>
|
||||||
<List
|
<List
|
||||||
//loadMore={loadMore}
|
//loadMore={loadMore}
|
||||||
dataSource={this.state.feed}
|
dataSource={this.state.feed}
|
||||||
renderItem={item => (
|
renderItem={item => (
|
||||||
<div id={item.id}>
|
<PostCard payload={item}/>
|
||||||
<PostCard payload={item} key={item.id} />
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
3
src/pages/explore/index.less
Normal file
3
src/pages/explore/index.less
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.exploreWrapper{
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,9 @@ import * as Icons from 'components/Icons'
|
|||||||
export default class Logout extends React.Component{
|
export default class Logout extends React.Component{
|
||||||
|
|
||||||
componentDidMount(){
|
componentDidMount(){
|
||||||
|
if (!this.props.app.session_valid) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
const dispatchLogout = () => this.props.dispatch({ type: "app/logout" })
|
const dispatchLogout = () => this.props.dispatch({ type: "app/logout" })
|
||||||
|
|
||||||
antd.Modal.confirm({
|
antd.Modal.confirm({
|
||||||
|
@ -128,8 +128,8 @@ class BackgroundImage extends ThemeConfigurator{
|
|||||||
key: "backgroundImage",
|
key: "backgroundImage",
|
||||||
model: { active: false, opacity: null, src: null },
|
model: { active: false, opacity: null, src: null },
|
||||||
|
|
||||||
textColor: this.rgbToScheme(getComputedStyle(document.getElementById("root")).color),
|
textColor: this.rgbToScheme(getComputedStyle(document.getElementById("appWrapper")).color),
|
||||||
overlayColor: this.rgbToScheme(getComputedStyle(document.getElementById("root")).backgroundColor),
|
overlayColor: this.rgbToScheme(getComputedStyle(document.getElementById("appWrapper")).backgroundColor),
|
||||||
|
|
||||||
processing: null,
|
processing: null,
|
||||||
customURL: '',
|
customURL: '',
|
||||||
|
@ -36,26 +36,20 @@
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root{
|
|
||||||
background-color: @AppTheme_global_background!important;
|
|
||||||
color: @AppTheme_global_color!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app{
|
.app{
|
||||||
&.interfaced{
|
&.interfaced{
|
||||||
height: calc(100% - @AppTheme_global_winavbar_height)!important;
|
height: calc(100% - @AppTheme_global_winavbar_height)!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dark_mode{
|
&.dark_mode{
|
||||||
filter: invert(100%);
|
|
||||||
|
|
||||||
:global{
|
:global{
|
||||||
.ant-card{
|
filter: invert(100%);
|
||||||
background: @AppTheme_global_background_dark!important;
|
img, svg, video {
|
||||||
|
filter: invert(100%);
|
||||||
|
color: @AppTheme_global_background;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
@ -64,7 +58,6 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
||||||
color: @AppTheme_global_color!important;
|
|
||||||
background-repeat: repeat-x;
|
background-repeat: repeat-x;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position-y: center;
|
background-position-y: center;
|
||||||
@ -89,6 +82,8 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
|
|
||||||
@ -101,7 +96,12 @@ body {
|
|||||||
line-height: @base-line-height;
|
line-height: @base-line-height;
|
||||||
|
|
||||||
font-family: @__Global_texted_font;
|
font-family: @__Global_texted_font;
|
||||||
background-color: @AppTheme_global_background!important;
|
color: @AppTheme_global_color!important;
|
||||||
|
background-color: @AppTheme_global_background;
|
||||||
|
|
||||||
|
&.dark{
|
||||||
|
background-color: @AppTheme_global_color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: @bp-small){
|
@media (max-width: @bp-small){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user