Browse Source

保存关注到本地,时间线分子模式

pull/6/head
hole-thu 4 years ago
parent
commit
a93e59069a
  1. 2
      src/App.js
  2. 7
      src/Attention.js
  3. 20
      src/Flows.css
  4. 155
      src/Flows.js
  5. 11
      src/UserAction.js
  6. 4
      src/flows_api.js

2
src/App.js

@ -5,6 +5,7 @@ import { Sidebar } from './Sidebar';
import { PressureHelper } from './PressureHelper'; import { PressureHelper } from './PressureHelper';
import { TokenCtx } from './UserAction'; import { TokenCtx } from './UserAction';
import { load_config, bgimg_style } from './Config'; import { load_config, bgimg_style } from './Config';
import { load_attentions } from './Attention.js';
import { listen_darkmode } from './infrastructure/functions'; import { listen_darkmode } from './infrastructure/functions';
import { LoginPopup, TitleLine } from './infrastructure/widgets'; import { LoginPopup, TitleLine } from './infrastructure/widgets';
@ -18,6 +19,7 @@ class App extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
load_config(); load_config();
load_attentions();
listen_darkmode( listen_darkmode(
{ default: undefined, light: false, dark: true }[ { default: undefined, light: false, dark: true }[
window.config.color_scheme window.config.color_scheme

7
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);
}

20
src/Flows.css

@ -319,3 +319,23 @@
height: 50vh; height: 50vh;
padding: 12px; 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;
}

155
src/Flows.js

@ -21,10 +21,9 @@ import {
import './Flows.css'; import './Flows.css';
import LazyLoad, { forceCheck } from './react-lazyload/src'; import LazyLoad, { forceCheck } from './react-lazyload/src';
import { TokenCtx, ReplyForm } from './UserAction'; import { TokenCtx, ReplyForm } from './UserAction';
import { API } from './flows_api'; import { API } from './flows_api';
import { cache } from './cache'; import { cache } from './cache';
import { save_attentions } from './Attention'
/* /*
const IMAGE_BASE = 'https://thimg.yecdn.com/'; const IMAGE_BASE = 'https://thimg.yecdn.com/';
@ -429,7 +428,8 @@ class FlowSidebar extends PureComponent {
loading_status: 'loading', loading_status: 'loading',
}); });
const prev_info = this.state.info; 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) => { .then((json) => {
this.setState({ this.setState({
loading_status: 'done', loading_status: 'done',
@ -439,6 +439,17 @@ class FlowSidebar extends PureComponent {
}), }),
}); });
console.log(json); 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({ this.syncState({
attention: json.attention, attention: json.attention,
info: Object.assign({}, prev_info, { info: Object.assign({}, prev_info, {
@ -1102,6 +1113,67 @@ function FlowChunk(props) {
} }
export class Flow extends PureComponent { 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 (
<>
<div className="aux-margin flow-submode-choice">
{submode_names.map((name, idx) => (
<a
key={idx}
className={submode === idx ? 'choiced' : ''}
onClick={this.set_submode.bind(this, idx)}
>
{name}
</a>
))}
</div>
<SubFlow
key={this.state.subflow_render_key}
show_sidebar={this.props.show_sidebar}
mode={this.props.mode}
submode={this.state.submode}
search_text={this.props.search_text}
token={this.props.token}
/>
</>
)
}
}
class SubFlow extends PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -1112,7 +1184,6 @@ export class Flow extends PureComponent {
title: '', title: '',
data: [], data: [],
}, },
can_export: false,
export_text: '', export_text: '',
loading_status: 'done', loading_status: 'done',
error_msg: null, error_msg: null,
@ -1137,7 +1208,7 @@ export class Flow extends PureComponent {
console.log('fetching page', page); console.log('fetching page', page);
cache(); cache();
if (this.state.mode === 'list') { if (this.state.mode === 'list') {
API.get_list(page, this.props.token) API.get_list(page, this.props.token, this.props.submode)
.then((json) => { .then((json) => {
if (page === 1 && json.data.length) { if (page === 1 && json.data.length) {
// update latest_post_id // update latest_post_id
@ -1235,33 +1306,52 @@ export class Flow extends PureComponent {
} }
} }
console.log(use_search, use_regex); console.log(use_search, use_regex);
API.get_attention(this.props.token)
.then((json) => { if (this.props.submode === 0) {
this.setState({ API.get_attention(this.props.token)
chunks: { .then((json) => {
title: `${ this.setState({
use_search chunks: {
? use_regex title: `${
? `Result for RegEx ${regex_search.toString()} in ` use_search
: `Result for "${this.state.search_param}" in ` ? use_regex
: '' ? `Result for RegEx ${regex_search.toString()} in `
}Attention List`, : `Result for "${this.state.search_param}" in `
data: !use_search : ''
? json.data }Attention List`,
: !use_regex data: !use_search
? json.data.filter((post) => { ? json.data
return this.state.search_param : !use_regex
? json.data.filter((post) => {
return this.state.search_param
.split(' ') .split(' ')
.every((keyword) => post.text.includes(keyword)); .every((keyword) => post.text.includes(keyword));
}) // Not using regex }) // Not using regex
: json.data.filter((post) => !!post.text.match(regex_search)), // Using regex : json.data.filter((post) => !!post.text.match(regex_search)), // Using regex
}, },
mode: 'attention_finished', mode: 'attention_finished',
loading_status: 'done', loading_status: 'done',
can_export: !use_search, });
}); if (!use_search) {
}) window.saved_attentions = Array.from(
.catch(failed); 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 { } else {
console.log('nothing to load'); console.log('nothing to load');
return; return;
@ -1314,8 +1404,9 @@ export class Flow extends PureComponent {
const should_deletion_detect = localStorage['DELETION_DETECT'] === 'on'; const should_deletion_detect = localStorage['DELETION_DETECT'] === 'on';
return ( return (
<div className="flow-container"> <div className="flow-container">
{this.state.can_export && (
<button type="button" onClick={this.gen_export.bind(this)}>导出</button> {this.state.mode === 'attention_finished' && this.props.submode == 0 && (
<button className="export-btn" type="button" onClick={this.gen_export.bind(this)}>导出</button>
)} )}
{this.state.export_text && ( {this.state.export_text && (

11
src/UserAction.js

@ -16,6 +16,7 @@ import {
API, API,
get_json, get_json,
} from './flows_api'; } from './flows_api';
import { save_attentions } from './Attention'
import './UserAction.css'; import './UserAction.css';
@ -266,7 +267,8 @@ export class ReplyForm extends Component {
}); });
let data = new URLSearchParams(); let data = new URLSearchParams();
data.append('pid', this.props.pid); let pid = this.props.pid;
data.append('pid', pid);
data.append('text', this.state.text); data.append('text', this.state.text);
fetch( fetch(
API_BASE + '/docomment', API_BASE + '/docomment',
@ -286,6 +288,13 @@ export class ReplyForm extends Component {
throw new Error(JSON.stringify(json)); throw new Error(JSON.stringify(json));
} }
let saved_attentions = window.saved_attentions;
if (!saved_attentions.includes(pid)) {
saved_attentions.unshift(pid)
window.saved_attentions = saved_attentions;
save_attentions();
}
this.setState({ this.setState({
loading_status: 'done', loading_status: 'done',
text: '', text: '',

4
src/flows_api.js

@ -136,11 +136,11 @@ export const API = {
return handle_response(response, true); return handle_response(response, true);
}, },
get_list: async (page, token) => { get_list: async (page, token, submode) => {
let response = await fetch( let response = await fetch(
API_BASE + '/getlist?p=' + page API_BASE + '/getlist?p=' + page
+ (window.config.no_c_post ? '&no_cw' : '') + (window.config.no_c_post ? '&no_cw' : '')
+ (window.config.by_c ? '&by_c' : ''), + (submode ? '&by_c' : ''),
{ {
headers: {'User-Token': token}, headers: {'User-Token': token},
}, },

Loading…
Cancel
Save