style(config): external controller config modal style tweak

This commit is contained in:
Haishan 2018-11-09 00:17:06 +08:00
parent b6da06c4ff
commit 9517d02996
8 changed files with 58 additions and 24 deletions

View file

@ -58,7 +58,7 @@ function APIConfig2() {
tabIndex="1" tabIndex="1"
onKeyDown={handleContentOnKeyDown} onKeyDown={handleContentOnKeyDown}
> >
<div className={s0.header}>RESTful API config for Clash</div> <div className={s0.header}>Clash External Controller Config</div>
<div className={s0.body}> <div className={s0.body}>
<div className={s0.group}> <div className={s0.group}>
<div className={s0.label}>Hostname and Port</div> <div className={s0.label}>Hostname and Port</div>

View file

@ -16,7 +16,7 @@
.inputs { .inputs {
display: flex; display: flex;
align-items: center; align-items: center;
div:nth-child(2) { input:nth-child(2) {
width: 120px; width: 120px;
margin-left: 10px; margin-left: 10px;
} }

View file

@ -7,6 +7,8 @@ import APIConfig from 'c/APIConfig';
import { closeModal } from 'd/modals'; import { closeModal } from 'd/modals';
import { fetchConfigs } from 'd/configs'; import { fetchConfigs } from 'd/configs';
import s0 from './APIDiscovery.module.scss';
const mapStateToProps = s => ({ const mapStateToProps = s => ({
modals: s.modals modals: s.modals
}); });
@ -26,6 +28,8 @@ export default function APIDiscovery() {
return ( return (
<Modal <Modal
isOpen={modals.apiConfig} isOpen={modals.apiConfig}
className={s0.content}
overlayClassName={s0.overlay}
shouldCloseOnOverlayClick={false} shouldCloseOnOverlayClick={false}
shouldCloseOnEsc={false} shouldCloseOnEsc={false}
onRequestClose={() => closeModal('apiConfig')} onRequestClose={() => closeModal('apiConfig')}

View file

@ -0,0 +1,7 @@
.content {
background: none;
}
.overlay {
background: #222;
}

View file

@ -1,12 +1,15 @@
.btn { .btn {
-webkit-appearance: none; -webkit-appearance: none;
outline: none; outline: none;
color: #ddd; color: #bebebe;
background: #606060; background: #232323;
border: 1px solid #555; border: 1px solid #555;
border-radius: 100px; border-radius: 100px;
padding: 6px 12px; padding: 6px 12px;
&:hover { &:hover {
background: darken(#555, 3%); background: #387cec;
border: 1px solid #387cec;
color: #fff;
// background: darken(#555, 3%);
} }
} }

View file

@ -1,17 +1,26 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Modal from 'react-modal'; import Modal from 'react-modal';
import cx from 'classnames';
import s0 from './Modal.module.scss'; import s0 from './Modal.module.scss';
function ModalAPIConfig({ isOpen, onRequestClose, children, ...otherProps }) { function ModalAPIConfig({
isOpen,
onRequestClose,
className,
overlayClassName,
children,
...otherProps
}) {
const contentCls = cx(className, s0.content);
const overlayCls = cx(overlayClassName, s0.overlay);
return ( return (
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
onRequestClose={onRequestClose} onRequestClose={onRequestClose}
contentLabel="API-Config" className={contentCls}
className={s0.content} overlayClassName={overlayCls}
overlayClassName={s0.overlay}
{...otherProps} {...otherProps}
> >
{children} {children}
@ -22,7 +31,9 @@ function ModalAPIConfig({ isOpen, onRequestClose, children, ...otherProps }) {
ModalAPIConfig.propTypes = { ModalAPIConfig.propTypes = {
isOpen: PropTypes.bool.isRequired, isOpen: PropTypes.bool.isRequired,
onRequestClose: PropTypes.func.isRequired, onRequestClose: PropTypes.func.isRequired,
children: PropTypes.node.isRequired children: PropTypes.node.isRequired,
className: PropTypes.string,
overlayClassName: PropTypes.string
}; };
export default React.memo(ModalAPIConfig); export default React.memo(ModalAPIConfig);

View file

@ -61,8 +61,9 @@
} }
body { body {
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica,
'Microsoft YaHei', '微软雅黑', Arial, sans-serif; Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol,
'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }

View file

@ -3,16 +3,13 @@ import { openModal } from 'd/modals';
import * as trafficAPI from 'a/traffic'; import * as trafficAPI from 'a/traffic';
const CompletedFetchConfigs = 'configs/CompletedFetchConfigs'; const CompletedFetchConfigs = 'configs/CompletedFetchConfigs';
const OptimisticUpdateConfigs = 'proxies/OptimisticUpdateConfigs'; const OptimisticUpdateConfigs = 'configs/OptimisticUpdateConfigs';
const MarkHaveFetchedConfig = 'configs/MarkHaveFetchedConfig';
export const getConfigs = s => s.configs; export const getConfigs = s => s.configs;
// maybe we should put this flag in the redux store
// but since is not related a UI element and only make sense to this chunk
// of code, I'm going to leave it here
let successfullyFetchedConfigsBefore = false;
export function fetchConfigs() { export function fetchConfigs() {
return async dispatch => { return async (dispatch, getState) => {
let res; let res;
try { try {
res = await configsAPI.fetchConfigs(); res = await configsAPI.fetchConfigs();
@ -41,13 +38,24 @@ export function fetchConfigs() {
payload payload
}); });
// side effect const configsCurr = getConfigs(getState());
if (successfullyFetchedConfigsBefore === false) {
successfullyFetchedConfigsBefore = true; if (configsCurr.haveFetchedConfig) {
// normally user will land on the "traffic chart" page first // normally user will land on the "traffic chart" page first
// calling this here will let the data start streaming // calling this here will let the data start streaming
// the traffic chart should already subscribed to the streaming // the traffic chart should already subscribed to the streaming
trafficAPI.fetchData(); trafficAPI.fetchData();
} else {
dispatch(markHaveFetchedConfig());
}
};
}
function markHaveFetchedConfig() {
return {
type: MarkHaveFetchedConfig,
payload: {
haveFetchedConfig: true
} }
}; };
} }
@ -91,15 +99,15 @@ const initialState = {
'redir-port': 0, 'redir-port': 0,
'allow-lan': false, 'allow-lan': false,
mode: 'Rule', mode: 'Rule',
'log-level': 'info' 'log-level': 'info',
///// /////
haveFetchedConfig: false
}; };
export default function reducer(state = initialState, { type, payload }) { export default function reducer(state = initialState, { type, payload }) {
switch (type) { switch (type) {
// case CompletedRequestDelayForProxy: case MarkHaveFetchedConfig:
// case OptimisticSwitchProxy:
case OptimisticUpdateConfigs: case OptimisticUpdateConfigs:
case CompletedFetchConfigs: { case CompletedFetchConfigs: {
return { ...state, ...payload }; return { ...state, ...payload };