1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict'
|
7 |
|
8 | import React, {PropTypes as types} from 'react'
|
9 | import {ApPureMixin} from 'apeman-react-mixins'
|
10 | import classnames from 'classnames'
|
11 | import arrayfilter from 'arrayfilter'
|
12 | import ApToastItem from './ap_toast_item'
|
13 |
|
14 |
|
15 | const ApToast = React.createClass({
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | propTypes: {
|
22 | message: types.string,
|
23 | duration: types.number,
|
24 | icon: types.string,
|
25 | name: types.string,
|
26 | onDismiss: types.func
|
27 | },
|
28 |
|
29 | mixins: [
|
30 | ApPureMixin
|
31 | ],
|
32 |
|
33 | statics: {
|
34 | itemJoiner: '____'
|
35 | },
|
36 |
|
37 | getInitialState () {
|
38 | return {
|
39 | items: ''
|
40 | }
|
41 | },
|
42 |
|
43 | getDefaultProps () {
|
44 | return {
|
45 | message: null,
|
46 | duration: 2000,
|
47 | icon: null,
|
48 | name: null,
|
49 | onDismiss: null
|
50 | }
|
51 | },
|
52 |
|
53 | render () {
|
54 | const s = this
|
55 | let { state, props } = s
|
56 |
|
57 | let valid = state.items.length
|
58 | if (!valid) {
|
59 | return null
|
60 | }
|
61 | return (
|
62 | <div className={ classnames('ap-toast', props.className, {}) }
|
63 | style={ Object.assign({}, props.style) }>
|
64 | <div className="ap-toast-inner">
|
65 | {s._renderToastItem()}
|
66 | </div>
|
67 | </div>
|
68 | )
|
69 | },
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 | componentWillMount () {
|
76 | const s = this
|
77 | },
|
78 |
|
79 | componentDidMount () {
|
80 | const s = this
|
81 | let { props } = s
|
82 | s.startTicking()
|
83 | s.pushToastItem(props.message)
|
84 | },
|
85 |
|
86 | componentWillReceiveProps (nextProps) {
|
87 | const s = this
|
88 | s.pushToastItem(nextProps.message)
|
89 | },
|
90 |
|
91 | componentWillUnmount () {
|
92 | const s = this
|
93 | s.stopTicking()
|
94 | },
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 | startTicking () {
|
101 | const s = this
|
102 | clearTimeout(s._tickTimer)
|
103 | s._ticking = true
|
104 | s.doTick()
|
105 | },
|
106 |
|
107 | stopTicking () {
|
108 | const s = this
|
109 | clearTimeout(s._tickTimer)
|
110 | s._ticking = false
|
111 | },
|
112 |
|
113 | doTick () {
|
114 | const s = this
|
115 | let { props } = s
|
116 | if (!s._ticking) {
|
117 | return
|
118 | }
|
119 | s._tickTimer = setTimeout(() => {
|
120 | s.shiftToastItem()
|
121 | s.doTick()
|
122 | }, props.duration)
|
123 | },
|
124 |
|
125 | pushToastItem (message) {
|
126 | const s = this
|
127 | if (!message) {
|
128 | return
|
129 | }
|
130 | let items = (s.state.items || '').split(ApToast.itemJoiner)
|
131 | let duplicate = items[ items.length - 1 ] === message
|
132 | if (duplicate) {
|
133 | return
|
134 | }
|
135 | s.setState({
|
136 | items: items.concat(message).join(ApToast.itemJoiner)
|
137 | })
|
138 | },
|
139 |
|
140 | shiftToastItem () {
|
141 | const s = this
|
142 | let { props } = s
|
143 | let items = (s.state.items || '').split(ApToast.itemJoiner)
|
144 | if (!items.length) {
|
145 | s.setState({ items: null })
|
146 | return
|
147 | }
|
148 | s.dismissToastItem(items[ 0 ])
|
149 | },
|
150 |
|
151 | dismissToastItem (message) {
|
152 | const s = this
|
153 | let { props } = s
|
154 | let items = (s.state.items || '').split(ApToast.itemJoiner)
|
155 | s.setState({
|
156 | items: items.filter((filtering) => filtering !== message)
|
157 | .join(ApToast.itemJoiner)
|
158 | })
|
159 | if (props.onDismiss) {
|
160 | props.onDismiss({ dismissed: message, name: props.name })
|
161 | }
|
162 | },
|
163 |
|
164 | handleToastItemTap (e) {
|
165 | const s = this
|
166 | let text = e.target.dataset[ 'text' ]
|
167 | s.dismissToastItem(text)
|
168 | },
|
169 |
|
170 |
|
171 |
|
172 |
|
173 | _ticking: false,
|
174 | _tickTimer: null,
|
175 | _renderToastItem () {
|
176 | const s = this
|
177 | let { state, props } = s
|
178 | return (state.items || '').split(ApToast.itemJoiner)
|
179 | .filter(arrayfilter.emptyReject())
|
180 | .map((text, i) => (
|
181 | <ApToastItem key={`toast-${text}-${i}`}
|
182 | text={text}
|
183 | icon={props.icon}
|
184 | onTap={s.handleToastItemTap}
|
185 | >
|
186 | </ApToastItem>
|
187 | )
|
188 | )
|
189 | }
|
190 | })
|
191 |
|
192 | export default ApToast
|