diff --git a/public/index.html b/public/index.html index d33c801..77e5f14 100644 --- a/public/index.html +++ b/public/index.html @@ -6,7 +6,7 @@ - + diff --git a/public/static/fonts_7/icomoon.css b/public/static/fonts_7/icomoon.css new file mode 100644 index 0000000..5004159 --- /dev/null +++ b/public/static/fonts_7/icomoon.css @@ -0,0 +1,101 @@ +@font-face { + font-family: 'icomoon'; + src: + url('icomoon.ttf?8qh3rt') format('truetype'), + url('icomoon.woff?8qh3rt') format('woff'), + url('icomoon.svg?8qh3rt#icomoon') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +.icon { + /* use !important to prevent issues with browser extensions that change fonts */ + /*noinspection CssNoGenericFontName*/ + font-family: 'icomoon' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.0625em; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-send:before { + content: "\e900"; +} +.icon-textfile:before { + content: "\e926"; +} +.icon-history:before { + content: "\e94d"; +} +.icon-reply:before { + content: "\e96b"; +} +.icon-quote:before { + content: "\e977"; +} +.icon-loading:before { + content: "\e979"; +} +.icon-login:before { + content: "\e98d"; +} +.icon-settings:before { + content: "\e994"; +} +.icon-stats:before { + content: "\e99b"; +} +.icon-locate:before { + content: "\e9b3"; +} +.icon-upload:before { + content: "\e9c3"; +} +.icon-flag:before { + content: "\e9cc"; +} +.icon-attention:before { + content: "\e9d3"; +} +.icon-star:before { + content: "\e9d7"; +} +.icon-star-ok:before { + content: "\e9d9"; +} +.icon-plus:before { + content: "\ea0a"; +} +.icon-about:before { + content: "\ea0c"; +} +.icon-close:before { + content: "\ea0d"; +} +.icon-logout:before { + content: "\ea14"; +} +.icon-refresh:before { + content: "\ea2e"; +} +.icon-forward:before { + content: "\ea42"; +} +.icon-back:before { + content: "\ea44"; +} +.icon-order-rev:before { + content: "\ea46"; + font-size: 1.2em; +} +.icon-github:before { + content: "\eab0"; +} diff --git a/public/static/fonts_7/icomoon.svg b/public/static/fonts_7/icomoon.svg new file mode 100644 index 0000000..2482297 --- /dev/null +++ b/public/static/fonts_7/icomoon.svg @@ -0,0 +1,34 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/static/fonts_7/icomoon.ttf b/public/static/fonts_7/icomoon.ttf new file mode 100644 index 0000000..20a0e38 Binary files /dev/null and b/public/static/fonts_7/icomoon.ttf differ diff --git a/public/static/fonts_7/icomoon.woff b/public/static/fonts_7/icomoon.woff new file mode 100644 index 0000000..1b7a936 Binary files /dev/null and b/public/static/fonts_7/icomoon.woff differ diff --git a/src/App.js b/src/App.js index 4ec35e8..85058a5 100644 --- a/src/App.js +++ b/src/App.js @@ -17,8 +17,7 @@ class App extends Component { load_config(); listen_darkmode({default: undefined, light: false, dark: true}[window.config.color_scheme]); this.state={ - sidebar_title: null, - sidebar_content: null, // determine status of sidebar + sidebar_stack: [[null,null]], // list of [status, content] mode: 'list', // list, single, search, attention search_text: null, flow_render_key: +new Date(), @@ -41,20 +40,39 @@ class App extends Component { } on_pressure() { - if(this.state.sidebar_title!==null) - this.setState((prevState)=>({ - sidebar_title: null, - sidebar_content: prevState.sidebar_content, - })); + if(this.state.sidebar_stack.length>1) + this.show_sidebar(null,null,'clear'); else this.set_mode('list',null); } - show_sidebar(title,content) { - this.setState({ - sidebar_title: title, - sidebar_content: content, - }); + show_sidebar(title,content,mode='push') { + if(mode==='push') { + this.setState((prevState)=>({ + sidebar_stack: prevState.sidebar_stack.concat([[title,content]]), + })); + } else if(mode==='pop') { + this.setState((prevState)=>{ + let ns=prevState.sidebar_stack.slice(); + ns.pop(); + return { + sidebar_stack: ns, + }; + }); + } else if(mode==='replace') { + this.setState((prevState)=>{ + let ns=prevState.sidebar_stack.slice(); + ns.pop(); + return { + sidebar_stack: ns.concat([[title,content]]), + }; + }); + } else if(mode==='clear') { + this.setState({ + sidebar_stack: [[null,null]], + }); + } else + throw new Error('bad show_sidebar mode'); } set_mode(mode,search_text) { @@ -102,11 +120,7 @@ class App extends Component {
)} - { - this.setState({ - sidebar_title: null, - }); - }} content={this.state.sidebar_content} title={this.state.sidebar_title} /> + ); } diff --git a/src/Flows.js b/src/Flows.js index b376263..a0ffbc3 100644 --- a/src/Flows.js +++ b/src/Flows.js @@ -19,10 +19,12 @@ const QUOTE_BLACKLIST=['23333','233333','66666','666666','10086','10000','100000 window.LATEST_POST_ID=parseInt(localStorage['_LATEST_POST_ID'],10)||0; +const DZ_NAME='洞主'; + function load_single_meta(show_sidebar,token,parents) { return (pid)=>{ - let title_elem=; - const color_picker=new ColorPicker(); + let color_picker=new ColorPicker(); + let title_elem='树洞 #'+pid; show_sidebar( title_elem,
@@ -46,7 +48,8 @@ function load_single_meta(show_sidebar,token,parents) { info={single.data} replies={replies.data} attention={replies.attention} token={token} show_sidebar={show_sidebar} color_picker={color_picker} deletion_detect={localStorage['DELETION_DETECT']==='on'} parents={parents} - /> + />, + 'replace' ) }) .catch((e)=>{ @@ -56,7 +59,8 @@ function load_single_meta(show_sidebar,token,parents) {

load_single_meta(show_sidebar,token,parents)(pid)}>重新加载

{''+e}

-
+
, + 'replace' ); }) }; @@ -142,6 +146,11 @@ class FlowItem extends PureComponent {
}
+ {!!this.props.do_filter_name && + {this.props.do_filter_name(DZ_NAME);}}> + + + } {!!parseInt(props.info.likenum,10) && {props.info.likenum}  @@ -334,18 +343,20 @@ class FlowSidebar extends PureComponent { // key for lazyload elem let view_mode_key=(this.state.rev ? 'y-' : 'n-')+(this.state.filter_name||'null'); - let replies_cnt={}; + let replies_cnt={[DZ_NAME]:1}; replies_to_show.forEach((r)=>{ if(replies_cnt[r.name]===undefined) replies_cnt[r.name]=0; replies_cnt[r.name]++; }); - let main_thread_elem=( + // hide main thread when filtered + let main_thread_elem=(this.state.filter_name && this.state.filter_name!==DZ_NAME) ? null : ( {this.show_reply_bar('',e);}}> {this.set_variant(null,variant);}} + do_filter_name={replies_cnt[DZ_NAME]>1 ? this.set_filter_name.bind(this) : null} /> ); @@ -364,7 +375,7 @@ class FlowSidebar extends PureComponent { - {(this.state.replies.length>1 || this.state.rev) && + {(this.state.replies.length>=1 || this.state.rev) &&    @@ -386,6 +397,15 @@ class FlowSidebar extends PureComponent { }
+ {!!this.state.filter_name && +
+

+ {this.set_filter_name(null)}}>还原 +  当前只看  + {this.state.filter_name} +

+
+ } {!this.state.rev && main_thread_elem } @@ -400,15 +420,6 @@ class FlowSidebar extends PureComponent { {parseInt(this.state.info.reply)-this.state.replies.length} 条回复被删除
} - {!!this.state.filter_name && -
-

- {this.set_filter_name(null)}}>还原 -  当前只看  - {this.state.filter_name} -

-
- } {replies_to_show.map((reply)=>( {this.show_reply_bar(reply.name,e);}}> @@ -433,24 +444,6 @@ class FlowSidebar extends PureComponent { } } -function FlowSidebarTitle(props) { - let last_pid=props.parents.length ? props.parents[props.parents.length-1] : null; - return ( - - 树洞  - {!!last_pid && - - load_single_meta(props.show_sidebar,props.token,props.parents.slice(0,-1))(last_pid)}> - #{last_pid} - -  →  - - } - #{props.pid} - - ); -} - class FlowItemRow extends PureComponent { constructor(props) { super(props); @@ -499,7 +492,7 @@ class FlowItemRow extends PureComponent { show_sidebar() { this.props.show_sidebar( - , + '树洞 #'+this.state.info.pid, { - if(page===1) + if(page===1 && json.data.length) { // update latest_post_id + let max_id=-1; json.data.forEach((x)=>{ - if(parseInt(x.pid,10)>(parseInt(localStorage['_LATEST_POST_ID'],10)||0)) - localStorage['_LATEST_POST_ID']=x.pid; + if(parseInt(x.pid,10)>max_id) + max_id=parseInt(x.pid,10); }); + localStorage['_LATEST_POST_ID']=''+max_id; + } this.setState((prev,props)=>({ chunks: { title: 'News Feed', diff --git a/src/Sidebar.js b/src/Sidebar.js index cec5f9b..31aa58d 100644 --- a/src/Sidebar.js +++ b/src/Sidebar.js @@ -5,26 +5,39 @@ export class Sidebar extends PureComponent { constructor(props) { super(props); this.sidebar_ref=React.createRef(); + this.do_close_bound=this.do_close.bind(this); + this.do_back_bound=this.do_back.bind(this); } componentDidUpdate(nextProps) { - if(this.props.content!==nextProps.content) { + if(this.props.stack!==nextProps.stack) { //console.log('sidebar top'); if(this.sidebar_ref.current) this.sidebar_ref.current.scrollTop=0; } } + do_close() { + this.props.show_sidebar(null,null,'clear'); + } + do_back() { + this.props.show_sidebar(null,null,'pop'); + } + render() { + let [cur_title,cur_content]=this.props.stack[this.props.stack.length-1]; return ( -
-
{e.preventDefault();e.target.click();}} /> +
+
{e.preventDefault();e.target.click();}} />
- {this.props.content} + {cur_content}
-    - {this.props.title} +    + {this.props.stack.length>2 && +    + } + {cur_title}
); diff --git a/src/Title.css b/src/Title.css index 330780e..c493e28 100644 --- a/src/Title.css +++ b/src/Title.css @@ -23,7 +23,7 @@ } .control-btn { - flex: 0 0 2em; + flex: 0 0 4.5em; text-align: center; color: black; border-radius: 5px; @@ -32,6 +32,17 @@ background-color: #555555; color: white; } +.control-btn-label { + margin-left: .25em; +} +@media screen and (max-width: 900px) { + .control-btn { + flex: 0 0 2em; + } + .control-btn-label { + display: none; + } +} .root-dark-mode .control-btn { color: var(--foreground-dark); @@ -42,11 +53,6 @@ opacity: 1; } -.control-btn .icon:before { - margin: .5em; - display: inline-block; -} - .control-search { flex: auto; color: black; diff --git a/src/Title.js b/src/Title.js index 063737c..253121d 100644 --- a/src/Title.js +++ b/src/Title.js @@ -132,10 +132,12 @@ class ControlBar extends PureComponent {