diff --git a/src/models/app.js b/src/models/app.js
index e451925b..8b336508 100755
--- a/src/models/app.js
+++ b/src/models/app.js
@@ -26,7 +26,8 @@ export default {
controlActive: false,
feedOutdated: false,
- app_settings: store.get('app_settings'),
+ app_settings: store.get(app_config.app_settings_storage),
+ app_theme: store.get(app_config.appTheme_container),
notifications: [],
locationQuery: {},
@@ -52,7 +53,7 @@ export default {
cancelRequest.forEach((value, key) => {
if (value.pathname !== window.location.pathname) {
- value.cancel(CANCEL_REQUEST_MESSAGE);
+ value.cancel('cancel request');
cancelRequest.delete(key);
}
});
@@ -113,6 +114,25 @@ export default {
}
});
},
+ *updateTheme({payload}, {call, put, select}){
+ if (!payload) return false;
+ let tmp = []
+
+ const keys = Object.keys(payload)
+ const values = Object.values(payload)
+ const lenght = keys.length
+
+ for (let i = 0; i < lenght; i++) {
+ let obj = {}
+ obj.key = keys[i]
+ obj.value = values[i]
+
+ tmp[i] = obj
+ }
+
+ return yield put({ type: 'handleUpdateTheme', payload: tmp });
+
+ },
},
reducers: {
updateState(state, { payload }) {
@@ -131,6 +151,12 @@ export default {
state.notifications = [];
},
+ handleUpdateTheme(state, { payload }) {
+ verbosity.debug(payload)
+ store.set(app_config.appTheme_container, payload);
+ state.app_theme = payload
+ },
+
disconnectServices(state) {
state.service_valid = false;
state.session_valid = false;
diff --git a/src/pages/debug/index.js b/src/pages/debug/index.js
index 141ad75b..35e8734c 100644
--- a/src/pages/debug/index.js
+++ b/src/pages/debug/index.js
@@ -14,7 +14,6 @@ import {
import classnames from 'classnames';
import { CloseOutlined } from '@ant-design/icons';
import endpoints_list from 'config/endpoints';
-import { Page } from 'components';
import styles from './index.less';
@@ -171,7 +170,7 @@ class RequestPage extends React.Component {
const { result, url, method, ParamsKeys, BodyKeys, visible } = this.state;
return (
-
+
{result}
-
+
);
}
}
diff --git a/src/pages/debug/theme.js b/src/pages/debug/theme.js
new file mode 100644
index 00000000..ed51cf58
--- /dev/null
+++ b/src/pages/debug/theme.js
@@ -0,0 +1,79 @@
+import React from 'react'
+import * as antd from 'antd'
+import * as themeLIB from 'core/libs/style'
+
+function getBase64(img, callback) {
+ const reader = new FileReader()
+ reader.addEventListener('load', () => callback(reader.result))
+ reader.readAsDataURL(img)
+ }
+
+export default class themedebug extends React.PureComponent {
+ state = {
+ textColor: {r: '255', g: '255', b: '255'},
+ overlayColor: {r: '0', g: '0', b: '0'},
+
+ optimal: null,
+ file: null,
+ fileURL: null,
+ }
+ ToogleUpload() {
+ this.setState({ uploader: !this.state.uploader })
+ }
+ handleDeleteFile = () => {
+ this.setState({ fileURL: null })
+ }
+ handleFileUpload = info => {
+ if (info.file.status === 'uploading') {
+ this.setState({ loading: true })
+ return
+ }
+ if (info.file.status === 'done') {
+ this.setState({ file: info.file.originFileObj, uploader: false })
+ getBase64(info.file.originFileObj, fileURL => {
+ this.setState({ fileURL, loading: false })
+ })
+ }
+ }
+
+ handleGetOptimal() {
+ const optimal = themeLIB.getOptimalOpacityFromIMG({ textColor: this.state.textColor, overlayColor: this.state.overlayColor, img: this.state.fileURL })
+ this.setState({ optimal: optimal })
+ }
+
+ schemeToRGB(values) {
+ return `rgb(${values.r}, ${values.g}, ${values.b})`
+ }
+
+ render(){
+
+ return(
+ this.onChangeSwitch(item)}
+ checked={settings.get(item.id)}
+ onChange={() => this.onChange(item)}
/>
)
case 'numeric':
@@ -41,29 +40,6 @@ class Base extends Component {
}
}
- SettingRender = data => {
- try {
- return (
-
- (
-
-
- {this.rendersets(item)}
-
- )}
- />
-
- )
- } catch (err) {
- return verbosity.log(err)
- }
- }
handleControlBar() {
const ListControls = [
@@ -76,7 +52,7 @@ class Base extends Component {
,
]
- ControlBar.set(ListControls)
+ control.set(ListControls)
}
saveChanges() {
@@ -87,39 +63,44 @@ class Base extends Component {
description:
'The configuration has been saved, it may for some configuration to make changes you need to reload the application',
})
- setTimeout(app._app.refresh(), 1000)
- ControlBar.close()
+ control.close()
}
- onChangeSwitch(item) {
+ onChange(item) {
try {
- this.handleControlBar()
- const to = !item.value
- const updatedValue = [...this.state.SettingRepo].map(ita =>
- ita === item ? Object.assign(ita, { value: to }) : ita
- )
- this.setState({ SettingRepo: updatedValue, forSave: true })
- verbosity.log(`Changing ${item.SettingID} to value ${to}`)
+ switch (item.type) {
+ case 'switch': {
+ item.to = !settings.get(item.id)
+ verbosity.debug(`Changing setting (${item.id}: ${settings.get(item.id)}) => ${item.to}`)
+ settings.set(item.id, item.to)
+ this.handleChange(item)
+
+ }
+ case 'numeric': {
+
+ }
+ default: {
+ return null
+ }
+ }
} catch (err) {
console.log(err)
}
}
- onChangeNumeric(value, item) {
- this.HandleChangeNumeric(value)
- }
- HandleChangeNumeric(item, value) {
+
+
+ handleChange(item) {
try {
- this.handleControlBar()
- console.log(item.SettingID, value)
- const updatedValue = [...this.state.SettingRepo].map(ita =>
- ita === item ? Object.assign(ita, { value: value }) : ita
+ const updatedValue = this.state.list.map(element =>
+ element.id === item.id ? Object.assign(element, { value: item.to }) : element
)
- this.setState({ SettingRepo: updatedValue, forSave: true })
- verbosity.log(`Changing ${item.SettingID} to value ${to}`)
+ this.setState({ list: updatedValue})
} catch (err) {
console.log(err)
}
}
+
+
render() {
return (
@@ -127,7 +108,19 @@ class Base extends Component {
Behaviors
- {this.SettingRender(this.state.SettingRepo)}
+ (
+
+
+ {this.renderSetting(item)}
+
+ )}
+ />
)
diff --git a/src/pages/settings/components/theme/index.js b/src/pages/settings/components/theme/index.js
index b6c46c88..4d366101 100644
--- a/src/pages/settings/components/theme/index.js
+++ b/src/pages/settings/components/theme/index.js
@@ -1,12 +1,35 @@
import React from 'react'
-import * as Feather from 'feather-reactjs'
+import * as Icons from 'components/Icons'
import * as antd from 'antd'
+import themeSettings from 'globals/theme_settings'
+import {connect} from 'umi'
+import styles from './index.less'
+import json_prune from 'core/libs/json_prune'
+
import { SketchPicker } from 'react-color';
+import { theme, getOptimalOpacityFromIMG, get_style_rule_value } from 'core/libs/style'
-import ColorThief from 'colorthief/dist/color-thief'
-var colorThief = new ColorThief();
+function getBase64(img, callback) {
+ const reader = new FileReader()
+ reader.addEventListener('load', () => callback(reader.result))
+ reader.readAsDataURL(img)
+}
+
+function toDataUrl(url, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = function() {
+ var reader = new FileReader();
+ reader.onloadend = function() {
+ callback(reader.result);
+ }
+ reader.readAsDataURL(xhr.response);
+ };
+ xhr.open('GET', url);
+ xhr.responseType = 'blob';
+ xhr.send();
+}
class BackgroundColor extends React.Component{
state = {
@@ -29,30 +52,219 @@ class BackgroundColor extends React.Component{
}
}
+@connect(({ app }) => ({ app }))
class BackgroundImage extends React.Component{
state = {
- results: []
+ customURL: '',
+ fileURL: null,
+ processing: null,
+ model: { active: false, opacity: null, src: null }
}
- search(key){
- if (!key) return false
- app.api_unsplash.search(key, (res) =>{
- console.log(res)
- this.setState({ results: res })
+ handleFileUpload = info => {
+ if (info.file.status === 'uploading') {
+ return this.setState({ processing: false })
+ }
+ if (info.file.status === 'done') {
+ this.setState({ processing: true })
+ getBase64(info.file.originFileObj, fileURL => {
+ this.setState({ fileURL: fileURL })
+ this.proccessBackground(fileURL)
+ })
+ }
+ }
+
+ handleCustomURL(url){
+ this.setState({ processing: true })
+ this.setState({ fileURL: url })
+
+ toDataUrl(url, fileURL => {
+ this.proccessBackground(fileURL)
})
}
- returnString(url){
- this.props.selectImg(`url(${url})`)
+
+ handleUpdate(payload){
+ if (!payload) {
+ payload = this.state.model
+ }
+ this.setState({ model: payload, processing: false })
+ this.props.dispatch({
+ type: 'app/updateTheme',
+ payload: { backgroundImage: payload }
+ });
}
+
+ handleErase(){
+ this.handleUpdate({})
+ }
+
+ handleExport(){
+ const string = JSON.stringify(this.state.model)
+ const exportCodeRender = () => {
+ if(string.length > 500){
+ return
+
+
Hey, this file is too much large!
+ So it couldn't be displayed.
+
+ }
+ return
+ {string}
+
+ }
+ antd.Modal.confirm({
+ title: ,
+ icon: null,
+ onOk: () => {
+ let tmp = document.createElement('a')
+ tmp.href = `data:text/json;charset=utf-8,${encodeURIComponent(string)}`
+ tmp.download="export.json"
+ tmp.click()
+ },
+ okText: <>Download as File> ,
+ cancelText: "Done",
+ content: exportCodeRender(),
+ });
+
+
+ }
+
+ proccessBackground(data){
+ getOptimalOpacityFromIMG({textColor: this.state.textColor, overlayColor: this.state.overlayColor, img: data}, (res) => {
+ this.handleUpdate({active: true, src: this.state.fileURL, opacity: res})
+ })
+ }
+
+ schemeToRGB(values){
+ const scheme = values || { r: '0', g: '0', b: '0' }
+ const r = scheme.r || '0'
+ const g = scheme.g || '0'
+ const b = scheme.b || '0'
+ return `rgb(${r}, ${g}, ${b})`
+ }
+
+ rgbToScheme(rgb){
+ const values = rgb.replace(/[^\d,]/g, '').split(',');
+ return {r: values[0], g: values[1], b: values[2]}
+ }
+
+ componentDidMount(){
+ const storaged = theme.get()["backgroundImage"]
+ if(storaged){
+ this.setState({ model: storaged })
+ }
+
+ let textColor = this.rgbToScheme(get_style_rule_value('#root', 'color'))
+ let overlayColor = this.rgbToScheme(get_style_rule_value('#root', 'backgroundColor'))
+
+ this.setState({
+ textColor: textColor,
+ overlayColor: overlayColor
+ })
+ }
+
+
render(){
+ const promiseState = async state => new Promise(resolve => this.setState(state, resolve));
+
+ const PreviewModel = () => {
+ return(
+
+
Preview
+ { this.state.model.src?
+
+
Sample text
+
Sample text
+
Sample text
+
Sample text
+
Some text here
+
Some text here
+
+
+

+
:
No Background
}
+
+ )
+ }
+
return (
<>
- Upload
+
+
Background Image
+
+
+
+
+
Enabled
+
{
+ promiseState(prevState => ({ model: { ...prevState.model, active: e }})).then(() => this.handleUpdate())
+ }}
+ checked={this.state.model.active}
+ />
+
+
+
+
Opacity
+
{
+ this.setState(
+ prevState => ({
+ model: {
+ ...prevState.model,
+ opacity: e/100
+ }
+ })
+ )
+ }} onAfterChange={() => this.handleUpdate()} value={this.state.model.opacity*100} />
+
+
+
Export Code
+
this.handleExport()}> Export
+
+
+
Erase
+
this.handleErase()} okText="Yes" cancelText="No">
+ Delete
+
+
+
+
+
+
+
- Unsplash
+
+
+
Upload
+
+
+ Upload from your files
+
+ } />
+
+
+
+
Or
+
+
+ Upload from URL
+
this.handleCustomURL(this.state.customURL)} onChange={e => this.setState({ customURL: e.target.value })} value={this.state.customURL} placeholder="http://example.com/my_coolest_image.jpg" />
+
+
+
+ {this.state.processing?
Processing image ...
: null}
+ {this.state.params? JSON.stringify(this.state.params) : null}
+
+
+
+
+ {/* Unsplash
this.search(value)} />
- (
this.returnString(item.urls.full)} src={item.urls.small} /> ) }/>
+ (
this.returnString(item.urls.full)} src={item.urls.small} /> ) }/> */}
>
)
}
@@ -62,96 +274,9 @@ export default class ThemeSettings extends React.PureComponent{
state = {
helper_visible: false,
helper_fragment: null,
- style: [],
+ style: theme.get(),
}
- 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 {
@@ -172,21 +297,6 @@ export default class ThemeSettings extends React.PureComponent{
}
- 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 })
@@ -195,25 +305,33 @@ export default class ThemeSettings extends React.PureComponent{
this.setState({ helper_visible: false, helper_fragment: null })
},
backgroundImage: () => {
- this.helper.open( this.handleChanges("backgroundImage", i)} />)
+ this.helper.open()
},
backgroundColor: () => {
- this.helper.open( this.handleChanges("backgroundColor", i)} />)
+ this.helper.open()
}
}
+
+
render(){
+ const settingClick = { backgroundImage: () => this.helper.backgroundImage(), backgroundColor: () => this.helper.backgroundColor() }
return(
-
Theme
-
-
-
-
-
+
Theme
+
(
+
+ {item.icon}{item.title} {this.state.style[item.id]? "Enabled" : "Disabled"}
+ {item.description}
+
+ )}
+ />
+
div {
+ width: 100%;
+ margin: 0 10px;
+ }
+}
+
+.background_image_uploader{
+ width: 100%;
+ margin: auto;
+ display: flex;
+ flex-direction: row;
+ text-align: center;
+
+ > div {
+ width: 100%;
+ margin: 0 10px;
+ }
+}
+
+.background_image_preview{
+ position: relative;
+ height: 50%;
+
+ img{
+ z-index: 9;
+ width: 100%;
+ border-radius: 8px;
+ }
+
+ .text_wrapper{
+ position: absolute;
+ z-index: 10;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ width: 100%;
+
+ h1{
+ font-size: 68px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/theme/base/index.less b/src/theme/base/index.less
index d1e2bf76..3a004d6f 100644
--- a/src/theme/base/index.less
+++ b/src/theme/base/index.less
@@ -11,12 +11,16 @@
@import './components/Menssaging.less';
@import './components/PostCard.less';
+@AppTheme_global_color: rgb(51, 51, 51);
+@AppTheme_global_color_accent: rgb(162, 162, 162);
+@AppTheme_global_background: rgb(248, 246, 248);
-@__Global_backgroud_image: "";
+@AppTheme_global_color_dark: rgb(162, 162, 162);
+@AppTheme_global_background_dark: rgb(51, 51, 51);
@__Global_general_font_family: "Poppins", sans-serif;
@__Global_texted_font: "Manrope", sans-serif;
-@__Global_alternative_font: "Netflix Sans";
+@__Global_alternative_font: "Netflix Sans", sans-serif;
@__Global_layout_backgroud: #F8F6F8;
@__Global_layout_color: #2d2d2d;
@@ -24,22 +28,19 @@
@__Global_layout_transitions-dur: 200ms;
@__Global_Components_transitions_dur: 150ms;
-
@__Global_SwapAnimDuration: 170ms;
@__Global_backdrop_backgroud: rgba(158, 158, 158, 0.5);
+@app_accent_gradient: linear-gradient(90deg, rgba(237,111,86,1) 0%, rgba(234,89,89,1) 100%);
+
@transition-ease-in: all 0.3s ease-out;
@transition-ease-out: all 0.3s ease-out;
@transition-ease-inout: all 150ms ease-in-out;
-
-
-
@Overlay_wrapper_hidden_width: 22vw;
@Overlay_wrapper_showFull_width: 94.2%;
@Overlay_wrapper_showHalf_width: 35vw;
-@Overlay_container_bg_background: #F8F6F8;
@Overlay_container_1_btn_backgroud: #4c4c4c;
@@ -72,12 +73,14 @@
#root {
overflow: hidden;
+ color: @AppTheme_global_color!important;
+ background-color: @AppTheme_global_background!important;
+ --accent_color: @AppTheme_global_color_accent;
}
body {
scroll-behavior: smooth;
height: 100%;
- background-color: transparent;
overflow: hidden;
@@ -86,9 +89,8 @@ body {
font-family: @__Global_texted_font;
- background-color: @primary_layout_backgroud;
-
+
}
@media (max-width: @bp-small){
diff --git a/src/theme/base/layout/LeftSider.less b/src/theme/base/layout/LeftSider.less
index fb1464d7..a07a5313 100644
--- a/src/theme/base/layout/LeftSider.less
+++ b/src/theme/base/layout/LeftSider.less
@@ -1,4 +1,4 @@
-@left_sider_color: #333;
+@left_sider_color: @AppTheme_global_color;
@left_sider_sizeIcons: 19px;
@left_sider_menu__onhover_backgroud: rgb(80, 80, 80);
@left_sider_menu__onhover_color: rgb(80, 80, 80);
\ No newline at end of file