@@ -3,64 +3,57 @@ import { MDCList } from "@material/list"
3
3
import { MDCRipple } from "@material/ripple"
4
4
import { BasicDialog , BasicDialogProps , TAG_DIALOG_WRAPPER_ID , showDialog } from "./BasicDialog"
5
5
import { consoleDebug } from "../../util/log"
6
- import { TagDialogPresenter } from "./TagDialogPresenter"
7
6
import ReactDOM from "react-dom"
8
7
import { initListItem } from "../list"
9
8
import { ERROR_HINT , LoadingHint } from "../react/LoadingHint"
10
9
import { HeightAnimationContainer } from "../animation/HeightAnimationContainer"
10
+ import { BasePostPaginateShow , BasePostPaginateShowProps , BasePostPaginateShowState , Post } from "../react/post/BasePostPaginateShow"
11
+ import { IPostPaginateShowPresenter } from "../react/post/IPostPaginateShowPresenter"
12
+ import { PostPaginateShowPresenter } from "../react/post/PostPaginateShowPresenter"
13
+ import { getSectionTypeByPath , SECTION_TYPE_OPERA , SECTION_TYPE_ORIGINAL , SectionType } from "../../base/constant"
11
14
// import "./TagEssayListDialog.scss"
12
15
13
16
interface DialogContentProps extends BasicDialogProps {
14
17
tag : string ,
15
18
}
16
19
17
20
interface DialogContentState {
18
- loading : boolean ,
19
- resultSize : number ,
20
- postList : PostItemData [ ]
21
- loadHint : string
21
+ dialogOpened : boolean ,
22
+ loadMoreId : number ,
22
23
}
23
24
24
25
export class TagDialog extends BasicDialog < DialogContentProps , DialogContentState > {
25
- presenter : TagDialogPresenter = null
26
26
heightAnimationContainer : HeightAnimationContainer = null
27
27
28
28
constructor ( props ) {
29
29
super ( props )
30
30
consoleDebug ( "TagDialogContent constructor" )
31
- this . onClickLoadMore = this . onClickLoadMore . bind ( this )
31
+ this . onListSizeChanged = this . onListSizeChanged . bind ( this )
32
32
// this.scrollToTopOnDialogOpen = false
33
33
this . listenScroll = true
34
- this . presenter = new TagDialogPresenter ( this )
35
34
this . state = {
36
- loading : true ,
37
- resultSize : 0 ,
38
- postList : [ ] ,
39
- loadHint : null
35
+ dialogOpened : false ,
36
+ loadMoreId : 0 ,
40
37
}
41
38
}
42
39
43
40
onDialogOpen ( ) {
44
41
super . onDialogOpen ( )
45
- // 检查是否应该触发fetch数据
46
- if ( this . state . postList . length == 0 ) {
47
- this . presenter . findTaggedPosts ( this . props . tag )
48
- }
42
+ this . setState ( { dialogOpened : true } )
49
43
}
50
44
51
45
onDialogClose ( ) {
52
46
super . onDialogClose ( )
53
- this . presenter . abortFetch ( )
54
- // this.presenter.reduceResult()
47
+ this . setState ( { dialogOpened : false } )
55
48
}
56
49
57
- onClickLoadMore ( ) {
58
- this . presenter . loadMore ( true )
59
- }
60
50
61
51
scrollNearToBottom ( ) : void {
62
- if ( this . state . loadHint == ERROR_HINT ) return
63
- this . presenter . loadMore ( false )
52
+ this . setState ( { loadMoreId : this . state . loadMoreId + 1 } )
53
+ }
54
+
55
+ onListSizeChanged ( ) {
56
+ this . heightAnimationContainer . update ( )
64
57
}
65
58
66
59
componentDidMount ( ) {
@@ -69,11 +62,6 @@ export class TagDialog extends BasicDialog<DialogContentProps, DialogContentStat
69
62
this . heightAnimationContainer = new HeightAnimationContainer ( this . rootE . querySelector ( ".height-animation-container" ) )
70
63
}
71
64
72
- componentDidUpdate ( prevProps : Readonly < BasicDialogProps > , prevState : Readonly < any > , snapshot ?: any ) : void {
73
- super . componentDidUpdate ( prevProps , prevState , snapshot )
74
- this . heightAnimationContainer . update ( )
75
- }
76
-
77
65
componentWillUnmount ( ) : void {
78
66
if ( this . heightAnimationContainer != null ) this . heightAnimationContainer . destroy ( )
79
67
}
@@ -88,36 +76,81 @@ export class TagDialog extends BasicDialog<DialogContentProps, DialogContentStat
88
76
89
77
dialogContent ( ) : JSX . Element {
90
78
consoleDebug ( "TagDialogContent render" )
79
+
80
+ return (
81
+ < div className = "height-animation-container" >
82
+ < ResultWrapper category = { "" } tag = { this . props . tag } pinedPosts = { [ ] } loadedPosts = { [ ] }
83
+ onUpdate = { this . onListSizeChanged } dialogOpened = { this . state . dialogOpened }
84
+ loadMoreId = { this . state . loadMoreId } />
85
+ </ div >
86
+ )
87
+ }
88
+ }
89
+
90
+ interface ResultWrapperProps extends BasePostPaginateShowProps {
91
+ dialogOpened : boolean
92
+ loadMoreId : number
93
+ }
94
+
95
+ class ResultWrapper extends BasePostPaginateShow < ResultWrapperProps > {
96
+
97
+ constructor ( props : ResultWrapperProps ) {
98
+ super ( props )
99
+ this . loadFirstPageOnMount = false
100
+ }
101
+
102
+ createPresenter ( ) : IPostPaginateShowPresenter {
103
+ return new PostPaginateShowPresenter ( this , true )
104
+ }
105
+
106
+ shouldComponentUpdate ( nextProps : Readonly < ResultWrapperProps > , nextState : Readonly < BasePostPaginateShowState > , nextContext : any ) : boolean {
107
+ if ( nextProps . loadMoreId > 0 && this . props . loadMoreId != nextProps . loadMoreId &&
108
+ ( this . presenter . isLastPage ( ) || this . state . loadHint == ERROR_HINT ) ) {
109
+ // 如果是最后一页,不触发加载
110
+ // 如果是异常状态,不触发加载,等待用户点击
111
+ return false
112
+ }
113
+ return true
114
+ }
115
+
116
+ componentDidUpdate ( prevProps : Readonly < ResultWrapperProps > , prevState : Readonly < BasePostPaginateShowState > , snapshot ?: any ) : void {
117
+ super . componentDidUpdate ( prevProps , prevState , snapshot )
118
+ if ( this . props . dialogOpened && ! prevProps . dialogOpened && this . state . posts . length == 0 ) {
119
+ this . loadFirstPage ( )
120
+ }
121
+ if ( ! this . props . dialogOpened && prevProps . dialogOpened ) {
122
+ this . presenter . abortLoad ( )
123
+ }
124
+ if ( this . props . loadMoreId > 0 && this . props . loadMoreId != prevProps . loadMoreId ) {
125
+ this . loadMore ( )
126
+ }
127
+ }
128
+
129
+ render ( ) : React . ReactNode {
91
130
let count : JSX . Element
92
- if ( this . state . postList . length == 0 ) {
131
+ if ( this . state . posts . length == 0 ) {
93
132
count = < > </ >
94
133
} else {
95
- count = < > < span > { this . state . resultSize } </ span > </ >
134
+ count = < > < span > { this . state . totalPostsSize } </ span > </ >
96
135
}
97
136
return (
98
137
< >
99
- < p className = "mdc-theme--on-surface" > 标记 { this . props . tag } 的{ count } 篇博文
138
+ < p > 标记 { this . props . tag } 的{ count } 篇博文
100
139
</ p >
101
-
102
- { /* <ProgressLinear loading={this.state.loading} /> */ }
103
- < div className = "height-animation-container" >
104
- < div >
105
- { this . state . postList != null && this . state . postList . length != 0 &&
106
- < PostResult list = { this . state . postList } />
107
- }
108
- { ( this . state . loading || this . state . loadHint != null ) &&
109
- < LoadingHint loading = { this . state . loading } loadHint = { this . state . loadHint } onClickHint = { this . onClickLoadMore } />
110
- }
111
- </ div >
112
- </ div >
140
+ { this . state . posts != null && this . state . posts . length != 0 &&
141
+ < PostResult list = { this . state . posts } />
142
+ }
143
+ { ( this . state . loading || this . state . loadHint != null ) &&
144
+ < LoadingHint loading = { this . state . loading } loadHint = { this . state . loadHint } onClickHint = { this . loadMoreByClick } />
145
+ }
113
146
</ >
114
147
)
115
148
}
116
149
}
117
150
118
151
119
152
interface PostResultProps {
120
- list : PostItemData [ ]
153
+ list : Post [ ]
121
154
}
122
155
123
156
class PostResult extends React . Component < PostResultProps , any > {
@@ -132,15 +165,42 @@ class PostResult extends React.Component<PostResultProps, any> {
132
165
new MDCList ( e )
133
166
}
134
167
168
+ getPostType ( item : Post ) : SectionType {
169
+ return getSectionTypeByPath ( item . path )
170
+ }
171
+
172
+ /**
173
+ * 获取一个文章要显示的块,包括author作者、actor演员、mention提到
174
+ * 显示,一共就2个block,用不同的颜色区分
175
+ */
176
+ getPostBlocks ( author : string , actor : Array < string > , mention : Array < string > , postType : SectionType ) : [ string [ ] , string [ ] ] {
177
+ if ( postType . identifier === SECTION_TYPE_ORIGINAL . identifier ) {
178
+ // 随笔,不显示author,显示actor和mention
179
+ return [ actor , mention ]
180
+ } else if ( postType . identifier === SECTION_TYPE_OPERA . identifier ) {
181
+ // 看剧,显示actor和mention
182
+ return [ actor , mention ]
183
+ } else {
184
+ // 其它类型,显示author和mention
185
+ return [ [ author ] , mention ]
186
+ }
187
+ }
188
+
135
189
render ( ) {
190
+ const items = this . props . list . map ( ( item ) => {
191
+ const postType = this . getPostType ( item )
192
+ const postBlocks = this . getPostBlocks ( item . author , item . actor , item . mention , postType )
193
+ // 两个chip列表
194
+ return new PostItemData ( item . path , item . title , item . date , postType . name , postBlocks [ 0 ] , postBlocks [ 1 ] )
195
+ } )
136
196
return (
137
197
< ul className = "mdc-deprecated-list" >
138
- { this . props . list . map ( ( item ) =>
198
+ { items . map ( ( item ) =>
139
199
< PostItem
140
200
key = { item . title + item . date }
141
201
data = { new PostItemData ( item . url , item . title , item . date , item . type , item . block1Array , item . block2Array ) }
142
- first = { this . props . list . indexOf ( item ) === 0 }
143
- last = { this . props . list . indexOf ( item ) === ( this . props . list . length - 1 ) }
202
+ first = { items . indexOf ( item ) === 0 }
203
+ last = { items . indexOf ( item ) === ( this . props . list . length - 1 ) }
144
204
/>
145
205
) }
146
206
</ ul >
0 commit comments