From a93e59069aaa59ad27d3a6c2b2b9304ccf24433f Mon Sep 17 00:00:00 2001 From: hole-thu Date: Fri, 17 Dec 2021 00:07:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=85=B3=E6=B3=A8=E5=88=B0?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=EF=BC=8C=E6=97=B6=E9=97=B4=E7=BA=BF=E5=88=86?= =?UTF-8?q?=E5=AD=90=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 2 + src/Attention.js | 7 ++ src/Flows.css | 20 ++++++ src/Flows.js | 159 ++++++++++++++++++++++++++++++++++++---------- src/UserAction.js | 11 +++- src/flows_api.js | 4 +- 6 files changed, 166 insertions(+), 37 deletions(-) create mode 100644 src/Attention.js diff --git a/src/App.js b/src/App.js index 0a6d652..27eec1b 100644 --- a/src/App.js +++ b/src/App.js @@ -5,6 +5,7 @@ import { Sidebar } from './Sidebar'; import { PressureHelper } from './PressureHelper'; import { TokenCtx } from './UserAction'; import { load_config, bgimg_style } from './Config'; +import { load_attentions } from './Attention.js'; import { listen_darkmode } from './infrastructure/functions'; import { LoginPopup, TitleLine } from './infrastructure/widgets'; @@ -18,6 +19,7 @@ class App extends Component { constructor(props) { super(props); load_config(); + load_attentions(); listen_darkmode( { default: undefined, light: false, dark: true }[ window.config.color_scheme diff --git a/src/Attention.js b/src/Attention.js new file mode 100644 index 0000000..73f291c --- /dev/null +++ b/src/Attention.js @@ -0,0 +1,7 @@ +export function load_attentions() { + window.saved_attentions = JSON.parse(localStorage['saved_attentions'] || '[]'); +} + +export function save_attentions() { + localStorage['saved_attentions'] = JSON.stringify(window.saved_attentions); +} diff --git a/src/Flows.css b/src/Flows.css index b6500df..1e53ef6 100644 --- a/src/Flows.css +++ b/src/Flows.css @@ -319,3 +319,23 @@ height: 50vh; padding: 12px; } + +.export-btn { + float: right; +} + +.flow-submode-choice { + display: inline-block; + color: white; +} + +.flow-submode-choice a { + margin: 10px; + color: white; +} + +.flow-submode-choice a.choiced { + margin: 10px; + color: white; + font-weight: bold; +} diff --git a/src/Flows.js b/src/Flows.js index 8acc20f..4e333ea 100644 --- a/src/Flows.js +++ b/src/Flows.js @@ -21,10 +21,9 @@ import { import './Flows.css'; import LazyLoad, { forceCheck } from './react-lazyload/src'; import { TokenCtx, ReplyForm } from './UserAction'; - import { API } from './flows_api'; - import { cache } from './cache'; +import { save_attentions } from './Attention' /* const IMAGE_BASE = 'https://thimg.yecdn.com/'; @@ -429,7 +428,8 @@ class FlowSidebar extends PureComponent { loading_status: 'loading', }); const prev_info = this.state.info; - API.set_attention(this.state.info.pid, !this.state.attention, this.props.token) + const pid = prev_info.pid; + API.set_attention(pid, !this.state.attention, this.props.token) .then((json) => { this.setState({ loading_status: 'done', @@ -439,6 +439,17 @@ class FlowSidebar extends PureComponent { }), }); console.log(json); + + let saved_attentions = window.saved_attentions; + if (json.attention && !saved_attentions.includes(pid)) { + saved_attentions.unshift(pid) + } else if (!json.attention && saved_attentions.includes(pid)) { + const idx = saved_attentions.indexOf(pid); + saved_attentions.splice(idx, 1) + } + window.saved_attentions = saved_attentions; + save_attentions(); + this.syncState({ attention: json.attention, info: Object.assign({}, prev_info, { @@ -1102,6 +1113,67 @@ function FlowChunk(props) { } export class Flow extends PureComponent { + constructor(props) { + super(props); + this.state = { + submode: this.props.mode == 'list' ? (window.config.by_c ? 1 : 0) : 0, + subflow_render_key: +new Date(), + } + } + + get_submode_names(mode) { + switch(mode) { + case('list'): + return ['最新', '最近回复', '近期热门']; + case('attention'): + return ['线上', '本地'] + } + return [] + } + + set_submode(submode) { + if (this.props.mode === 'list' && submode === 2) { + alert('将在下个版本提供'); + return; + } + this.setState({ + submode: submode, + subflow_render_key: +new Date(), + }); + } + + render() { + const { submode } = this.state; + const submode_names = this.get_submode_names(this.props.mode) + return ( + <> +
+ {submode_names.map((name, idx) => ( + + {name} + + ))} +
+ + + + ) + } +} + + +class SubFlow extends PureComponent { constructor(props) { super(props); this.state = { @@ -1112,7 +1184,6 @@ export class Flow extends PureComponent { title: '', data: [], }, - can_export: false, export_text: '', loading_status: 'done', error_msg: null, @@ -1137,7 +1208,7 @@ export class Flow extends PureComponent { console.log('fetching page', page); cache(); if (this.state.mode === 'list') { - API.get_list(page, this.props.token) + API.get_list(page, this.props.token, this.props.submode) .then((json) => { if (page === 1 && json.data.length) { // update latest_post_id @@ -1235,33 +1306,52 @@ export class Flow extends PureComponent { } } console.log(use_search, use_regex); - API.get_attention(this.props.token) - .then((json) => { - this.setState({ - chunks: { - title: `${ - use_search - ? use_regex - ? `Result for RegEx ${regex_search.toString()} in ` - : `Result for "${this.state.search_param}" in ` - : '' - }Attention List`, - data: !use_search - ? json.data - : !use_regex - ? json.data.filter((post) => { - return this.state.search_param + + if (this.props.submode === 0) { + API.get_attention(this.props.token) + .then((json) => { + this.setState({ + chunks: { + title: `${ + use_search + ? use_regex + ? `Result for RegEx ${regex_search.toString()} in ` + : `Result for "${this.state.search_param}" in ` + : '' + }Attention List`, + data: !use_search + ? json.data + : !use_regex + ? json.data.filter((post) => { + return this.state.search_param .split(' ') .every((keyword) => post.text.includes(keyword)); - }) // Not using regex - : json.data.filter((post) => !!post.text.match(regex_search)), // Using regex - }, - mode: 'attention_finished', - loading_status: 'done', - can_export: !use_search, - }); - }) - .catch(failed); + }) // Not using regex + : json.data.filter((post) => !!post.text.match(regex_search)), // Using regex + }, + mode: 'attention_finished', + loading_status: 'done', + }); + if (!use_search) { + window.saved_attentions = Array.from( + new Set([ + ...window.saved_attentions, + ...json.data.map(post => post.pid) + ]) + ).sort().reverse(); + save_attentions(); + } + }) + .catch(failed); + } else if (this.props.submode === 1) { + this.setState({ + title: 'Attention List: Local', + data: [], + export_text: `以下是浏览器本地保存的关注列表,将在下个版本提供直接展示\n\n#${ + window.saved_attentions.join('\n#') + }` + }); + } } else { console.log('nothing to load'); return; @@ -1274,7 +1364,7 @@ export class Flow extends PureComponent { })); } } - + on_scroll(event) { if (event.target === document) { const avail = @@ -1314,10 +1404,11 @@ export class Flow extends PureComponent { const should_deletion_detect = localStorage['DELETION_DETECT'] === 'on'; return (
- {this.state.can_export && ( - + + {this.state.mode === 'attention_finished' && this.props.submode == 0 && ( + )} - + {this.state.export_text && (