update topbar style
This commit is contained in:
@@ -2,7 +2,6 @@ import React, {Component} from 'react';
|
||||
import {Flow} from './Flows';
|
||||
import {Title} from './Title';
|
||||
import {Sidebar} from './Sidebar';
|
||||
import {ControlBar} from './ControlBar';
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
@@ -33,9 +32,8 @@ class App extends Component {
|
||||
return (
|
||||
<div>
|
||||
<div className="bg-img" />
|
||||
<Title callback={this.show_sidebar.bind(this)} />
|
||||
<Title callback={this.show_sidebar.bind(this)} set_search_text={this.set_search_text.bind(this)} />
|
||||
<div className="left-container">
|
||||
<ControlBar set_search_text={this.set_search_text.bind(this)} />
|
||||
<Flow key={this.state.flow_render_key}
|
||||
callback={this.show_sidebar.bind(this)} search_text={this.state.search_text}
|
||||
/>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
.centered-line {
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.centered-line::before,
|
||||
.centered-line::after {
|
||||
background-color: #fff;
|
||||
background-color: #000;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 1px;
|
||||
@@ -26,6 +24,15 @@
|
||||
margin-right: -50%;
|
||||
}
|
||||
|
||||
.title-line {
|
||||
color: #fff;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.title-line::before,
|
||||
.title-line::after {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.bg-img {
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
|
||||
@@ -22,9 +22,9 @@ export function Time(props) {
|
||||
);
|
||||
}
|
||||
|
||||
export function CenteredLine(props) {
|
||||
export function TitleLine(props) {
|
||||
return (
|
||||
<p className="centered-line aux-margin">
|
||||
<p className="centered-line title-line aux-margin">
|
||||
<span>{props.text}</span>
|
||||
</p>
|
||||
)
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
.control-bar {
|
||||
display: flex;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.control-bar .refresh-btn {
|
||||
flex: 0 0 100px;
|
||||
color: black;
|
||||
background-color: rgba(255,255,255,.9);
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.control-bar input {
|
||||
flex: auto;
|
||||
color: black;
|
||||
background-color: rgba(255,255,255,.9);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import React, {Component} from 'react';
|
||||
import './ControlBar.css';
|
||||
|
||||
export class ControlBar extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
search_text: '',
|
||||
};
|
||||
this.set_search_text=props.set_search_text;
|
||||
}
|
||||
|
||||
on_change(event) {
|
||||
this.setState({
|
||||
search_text: event.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
on_keypress(event) {
|
||||
if(event.key==='Enter')
|
||||
this.set_search_text(this.state.search_text);
|
||||
}
|
||||
|
||||
do_refresh() {
|
||||
this.setState({
|
||||
search_text: '',
|
||||
});
|
||||
this.set_search_text(null);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="control-bar aux-margin">
|
||||
<a className="refresh-btn" onClick={this.do_refresh.bind(this)}>最新树洞</a>
|
||||
|
||||
<input value={this.state.search_text} placeholder="搜索"
|
||||
onChange={this.on_change.bind(this)} onKeyPress={this.on_keypress.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -16,20 +16,20 @@
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.left-container .aux-margin,
|
||||
.aux-margin,
|
||||
.left-container .flow-item {
|
||||
margin-left: 50px;
|
||||
}
|
||||
.left-container .aux-margin {
|
||||
.aux-margin {
|
||||
width: calc(100% - 2 * 50px);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.left-container .aux-margin,
|
||||
.aux-margin,
|
||||
.left-container .flow-item {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.left-container .aux-margin {
|
||||
.aux-margin {
|
||||
width: calc(100% - 2 * 10px);
|
||||
}
|
||||
}
|
||||
|
||||
43
src/Flows.js
43
src/Flows.js
@@ -1,5 +1,5 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Time, CenteredLine} from './Common.js';
|
||||
import {Time, TitleLine} from './Common.js';
|
||||
import './Flows.css';
|
||||
import LazyLoad from 'react-lazyload';
|
||||
|
||||
@@ -97,7 +97,7 @@ class FlowItemRow extends Component {
|
||||
function FlowChunk(props) {
|
||||
return (
|
||||
<div className="flow-chunk">
|
||||
<CenteredLine text={props.title} />
|
||||
<TitleLine text={props.title} />
|
||||
{props.list.map((info)=>(
|
||||
<LazyLoad key={info.pid} offset={500} height="15em">
|
||||
<FlowItemRow info={info} callback={props.callback} />
|
||||
@@ -111,7 +111,11 @@ export class Flow extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
mode: props.search_text===null ? 'list' : 'search',
|
||||
mode: (
|
||||
props.search_text===null ? 'list' :
|
||||
props.search_text.charAt(0)==='#' ? 'single' :
|
||||
'search'
|
||||
),
|
||||
search_param: props.search_text,
|
||||
loaded_pages: 0,
|
||||
chunks: [],
|
||||
@@ -154,15 +158,42 @@ export class Flow extends Component {
|
||||
if(json.code!==0)
|
||||
throw new Error(json.code);
|
||||
const finished=json.data.length<SEARCH_PAGESIZE;
|
||||
this.setState((prev,props)=>({
|
||||
this.setState({
|
||||
chunks: [{
|
||||
title: 'Result for "'+this.state.search_param+'"',
|
||||
data: json.data,
|
||||
mode: finished ? 'search_finished' : 'search',
|
||||
}],
|
||||
loading: false,
|
||||
}));
|
||||
});
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.trace(err);
|
||||
alert('load failed');
|
||||
});
|
||||
} else if(this.state.mode==='single') {
|
||||
const pid=parseInt(this.state.search_param.substr(1),10);
|
||||
fetch(
|
||||
'http://www.pkuhelper.com:10301/services/pkuhole/api.php?action=getone'+
|
||||
'&pid='+pid
|
||||
)
|
||||
.then((res)=>res.json())
|
||||
.then((json)=>{
|
||||
if(json.code!==0)
|
||||
throw new Error(json.code);
|
||||
this.setState({
|
||||
chunks: [{
|
||||
title: 'PID = '+pid,
|
||||
data: [json.data],
|
||||
mode: 'single_finished',
|
||||
}],
|
||||
loading: false,
|
||||
});
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.trace(err);
|
||||
alert('load failed');
|
||||
});
|
||||
}
|
||||
this.setState((prev,props)=>({
|
||||
loaded_pages: prev.loaded_pages+1,
|
||||
@@ -195,7 +226,7 @@ export class Flow extends Component {
|
||||
{this.state.chunks.map((chunk)=>(
|
||||
<FlowChunk title={chunk.title} list={chunk.data} key={chunk.title} callback={this.props.callback} />
|
||||
))}
|
||||
<CenteredLine text={this.state.loading ? 'Loading...' : '© xmcp'} />
|
||||
<TitleLine text={this.state.loading ? 'Loading...' : '© xmcp'} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
.title {
|
||||
.title-bar {
|
||||
z-index: 1;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
top: -6em;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
font-size: 1.5em;
|
||||
height: 9em;
|
||||
background-color: rgba(255,255,255,.8);
|
||||
padding: 0 50px;
|
||||
box-shadow: 0 0 25px #999;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.title-links {
|
||||
float: right;
|
||||
display: inline-block;
|
||||
font-size: .7em;
|
||||
|
||||
.title {
|
||||
font-size: 2em;
|
||||
line-height: 3em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.control-bar {
|
||||
display: flex;
|
||||
margin-top: .5em;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.control-bar .refresh-btn {
|
||||
flex: 0 0 100px;
|
||||
color: black;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
border: 1px solid black;
|
||||
}
|
||||
.control-bar input {
|
||||
flex: auto;
|
||||
color: black;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
}
|
||||
65
src/Title.js
65
src/Title.js
@@ -1,17 +1,13 @@
|
||||
import React, {Component} from 'react';
|
||||
import './Title.css';
|
||||
|
||||
export function Title(props) {
|
||||
return (
|
||||
<div className="title">
|
||||
<div className="title-links">
|
||||
<a onClick={()=>{props.callback(
|
||||
'关于 P大树洞(非官方) 网页版',
|
||||
<div class="box">
|
||||
const HELP_TEXT=(
|
||||
<div className="box">
|
||||
<p>使用提示:</p>
|
||||
<ul>
|
||||
<li>为保证使用体验,请使用 Chrome 浏览器 stable 分支最新版</li>
|
||||
<li>在列表中点击帖子可以显示全部回复</li>
|
||||
<li>搜索框输入 #472865 等可以查看指定 ID 的树洞</li>
|
||||
</ul>
|
||||
<p>使用本网站时,您需要了解并同意:</p>
|
||||
<ul>
|
||||
@@ -35,10 +31,63 @@ export function Title(props) {
|
||||
GNU General Public License for more details.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
class ControlBar extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
search_text: '',
|
||||
};
|
||||
this.set_search_text=props.set_search_text;
|
||||
}
|
||||
|
||||
on_change(event) {
|
||||
this.setState({
|
||||
search_text: event.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
on_keypress(event) {
|
||||
if(event.key==='Enter')
|
||||
this.set_search_text(this.state.search_text);
|
||||
}
|
||||
|
||||
do_refresh() {
|
||||
window.scrollTo(0,0);
|
||||
this.setState({
|
||||
search_text: '',
|
||||
});
|
||||
this.set_search_text(null);
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="control-bar">
|
||||
<a className="refresh-btn" onClick={this.do_refresh.bind(this)}>最新树洞</a>
|
||||
|
||||
<input value={this.state.search_text} placeholder="搜索 或 #PID"
|
||||
onChange={this.on_change.bind(this)} onKeyPress={this.on_keypress.bind(this)}
|
||||
/>
|
||||
|
||||
<a onClick={()=>{this.props.callback(
|
||||
'关于 P大树洞(非官方) 网页版',
|
||||
HELP_TEXT
|
||||
)}}>Help</a>
|
||||
<a href="https://github.com/xmcp/ashole" target="_blank">GitHub</a>
|
||||
</div>
|
||||
P大树洞(非官方)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function Title(props) {
|
||||
return (
|
||||
<div className="title-bar">
|
||||
<div className="aux-margin">
|
||||
<p className="title centered-line">P大树洞</p>
|
||||
<ControlBar callback={props.callback} set_search_text={props.set_search_text} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user