Skip to content

Commit

Permalink
Merge pull request #30 from just4fun/v1.6.0
Browse files Browse the repository at this point in the history
v1.6.0
  • Loading branch information
just4fun authored May 20, 2018
2 parents 1942d01 + bf5be0d commit a44c826
Show file tree
Hide file tree
Showing 44 changed files with 907 additions and 174 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ For all officially recommended clients, please visit http://bbs.uestc.edu.cn/for

![app_icon](https://cloud.githubusercontent.com/assets/7512625/18613513/348f7322-7daf-11e6-902d-94776bb55670.jpg)

## Status (v1.5.2)
## Status (v1.6.0)

[<img width="250" alt="download_on_the_app_store" src="https://user-images.githubusercontent.com/7512625/27969868-353f554c-637f-11e7-869d-3963933461ca.png">](https://itunes.apple.com/cn/app/qing-shui-he-pan-stuhome/id1190564355)

Expand Down Expand Up @@ -44,16 +44,18 @@ For all officially recommended clients, please visit http://bbs.uestc.edu.cn/for
- [x] Favor topic
- [x] Upload images
- [x] Emoji
- [x] Show friend list to @
- [ ] Report objectionable content
- [ ] Vote
- [ ] Create vote
- [x] Join in vote
- [x] View vote results
- [x] Search
- [x] Notifications
- [x] View list mentioned(@) me
- [x] View list mentioned (@) me
- [x] View list replied me
- [x] View private messages
- [x] View system notifications
- [x] Notification alert
- [ ] Individual
- [x] View my recent topics
Expand Down
2 changes: 1 addition & 1 deletion ios/stuhome/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.5.2</string>
<string>1.6.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
9 changes: 7 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "stuhome",
"version": "1.5.2",
"version": "1.6.0",
"description": "An iOS client for http://bbs.uestc.edu.cn/ written in React Native with Redux.",
"author": "just4fun <[email protected]>",
"scripts": {
Expand Down Expand Up @@ -34,6 +34,7 @@
"react-native-scrollable-tab-view": "0.8.0",
"react-native-search-bar": "3.1.0",
"react-native-smart-emoji-picker": "0.1.0",
"react-native-smart-timer-enhance": "^1.0.3",
"react-native-sticky-keyboard-accessory": "0.1.1",
"react-native-vector-icons": "4.4.3",
"react-navigation": "1.0.3",
Expand Down
5 changes: 5 additions & 0 deletions src/actions/message/notifyListAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ export const REQUEST = Symbol();
export const INVALIDATE = Symbol();
export const MARK_AT_ME_AS_READ = Symbol();
export const MARK_REPLY_AS_READ = Symbol();
export const MARK_SYSTEM_AS_READ = Symbol();
export const fetchNotifyList = createAction(REQUEST);
export const invalidateNotifyList = createAction(INVALIDATE);

const markAtMeAsRead = createAction(MARK_AT_ME_AS_READ);
const markReplyAsRead = createAction(MARK_REPLY_AS_READ);
const markSystemAsRead = createAction(MARK_SYSTEM_AS_READ);

// Update unread message count immediately instead of
// clearing them with next poll after 0 ~ 15s.
export const successfulCallback = (payload) => {
Expand All @@ -17,6 +20,8 @@ export const successfulCallback = (payload) => {
return markAtMeAsRead();
case 'post':
return markReplyAsRead();
case 'system':
return markSystemAsRead();
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/actions/user/friendListAction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createAction } from 'redux-actions';

export const REQUEST = Symbol();
export const INVALIDATE = Symbol();
export const fetchFriendList = createAction(REQUEST);
export const invalidateFriendList = createAction(INVALIDATE);

export const REQUEST_STARTED = Symbol();
export const REQUEST_COMPELTED = Symbol();
export const REQUEST_FAILED = Symbol();
export const request = createAction(REQUEST_STARTED);
// return 2nd argument as `meta` field
export const success = createAction(REQUEST_COMPELTED, null, (...args) => args[1]);
export const failure = createAction(REQUEST_FAILED);
210 changes: 210 additions & 0 deletions src/components/3rd_party/LoadingSpinnerOverlay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import React, {
Component,
} from 'react'
import {
View,
Modal,
StyleSheet,
Animated,
Easing,
Dimensions,
ActivityIndicator,
ActivityIndicatorIOS,
ProgressBarAndroid,
} from 'react-native'

import TimerEnhance from 'react-native-smart-timer-enhance'

const styles = StyleSheet.create({
overlay: {
position: 'absolute',
left: 0,
top: 0,
zIndex: 998,
},
container: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
position: 'absolute',
borderRadius: 8,
padding: 20.5,
left: -9999,
top: -9999,
zIndex: 999,
},
})
const noop = () => {}

class LoadingSpinnerOverlay extends Component {

static defaultProps = {
duration: 255,
delay: 0,
marginTop: 0,
modal: true,
}

constructor(props) {
super(props)
this.state = {
visible: false,
opacity: new Animated.Value(0),
children: props.children,
modal: props.modal,
marginTop: props.marginTop,
}
this._loadingSpinnerWidth = null
this._loadingSpinnerHeight = null
this._loadingSpinnerShowAnimation = null
this._loadingSpinnerHideAnimation = null
this._loadingSpinnerAnimationToggle = null
}

render() {
let loadingSpinner = this._renderLoadingSpinner()
return this._renderOverLay(loadingSpinner)
}

_renderOverLay(loadingSpinner) {
let {width: deviceWidth, height: deviceHeight,} = Dimensions.get('window')
return (
this.state.modal ?
(this.state.marginTop === 0 ?
<Modal animationType={'none'} transparent={true} visible={this.state.visible} onRequestClose={noop}>
{loadingSpinner}
</Modal> :
(this.state.visible ?
<View
style={[ styles.overlay, {marginTop: this.props.marginTop, width: deviceWidth, height: deviceHeight - this.props.marginTop,}, this.props.overlayStyle, ]}>
{loadingSpinner}
</View> : null))
: loadingSpinner
)
}

_renderLoadingSpinner() {
let children
if(this.state.children == null) {
children = this._renderActivityIndicator()
}
else {
children = React.Children.map(this.state.children, (child) => {
if (!React.isValidElement(child)) {
return null
}
return child
})
}
return (
this.state.visible ?
<Animated.View
ref={ component => this._container = component }
onLayout={this._onLoadingSpinnerLayout}
style={[styles.container, this.props.style, {opacity:this.state.opacity, }]}>
{children}
</Animated.View> : null
)
}

show({modal = this.state.modal, marginTop = this.state.marginTop, children = this.state.children, duration = this.props.duration, easing = Easing.linear, delay = this.props.delay, animationEnd,}
= {modal: this.state.modal, marginTop: this.state.marginTop, children: this.state.children, duration: this.props.duration, easing: Easing.linear, delay: this.props.delay,}) {

this._loadingSpinnerShowAnimation && this._loadingSpinnerShowAnimation.stop()
this._loadingSpinnerHideAnimation && this._loadingSpinnerHideAnimation.stop()
this._loadingSpinnerAnimationToggle && this.clearTimeout(this._loadingSpinnerAnimationToggle)

if(this.state.visible) {
this._setLoadingSpinnerOverlayPosition({modal, marginTop})
}

this.setState({
children,
modal,
marginTop,
visible: true,
})

this._loadingSpinnerShowAnimation = Animated.timing(
this.state.opacity,
{
toValue: 1,
duration,
easing,
delay,
}
)
this._loadingSpinnerShowAnimation.start(() => {
this._loadingSpinnerShowAnimation = null
animationEnd && animationEnd()
})
}

hide({duration = this.props.duration, easing = Easing.linear, delay = this.props.delay, animationEnd,}
= {duration: this.props.duration, easing: Easing.linear, delay: this.props.delay,}) {

this._loadingSpinnerShowAnimation && this._loadingSpinnerShowAnimation.stop()
this._loadingSpinnerHideAnimation && this._loadingSpinnerHideAnimation.stop()
this.clearTimeout(this._loadingSpinnerAnimationToggle)

this._loadingSpinnerHideAnimation = Animated.timing(
this.state.opacity,
{
toValue: 0,
duration,
easing,
delay,
}
)
this._loadingSpinnerHideAnimation.start( () => {
this._loadingSpinnerHideAnimation = null
this.setState({
visible: false,
})
animationEnd && animationEnd()
})
}

_onLoadingSpinnerLayout = (e) => {
this._loadingSpinnerWidth = e.nativeEvent.layout.width
this._loadingSpinnerHeight = e.nativeEvent.layout.height
this._setLoadingSpinnerOverlayPosition()
}

_setLoadingSpinnerOverlayPosition({modal, marginTop} = {modal: this.state.modal, marginTop: this.state.marginTop}) {
if(!this._loadingSpinnerWidth || !this._loadingSpinnerHeight) {
return
}
let {width: deviceWidth, height: deviceHeight,} = Dimensions.get('window')
let left = (deviceWidth - this._loadingSpinnerWidth) / 2
let top = (deviceHeight - this._loadingSpinnerHeight) / 2 - (modal && marginTop === 0 ? 0 : marginTop)
this._container.setNativeProps({
style: {
left,
top,
}
})
}

_renderActivityIndicator() {
return ActivityIndicator ? (
<ActivityIndicator
style={{position: 'relative', left: 1, top: 1,}}
animating={true}
color={'#fff'}
size={'large'}/>
) : Platform.OS == 'android' ?
(
<ProgressBarAndroid
color={'#fff'}
styleAttr={'large'}/>

) : (
<ActivityIndicatorIOS
animating={true}
color={'#fff'}
size={'large'}/>
)
}

}

export default TimerEnhance(LoadingSpinnerOverlay)
16 changes: 9 additions & 7 deletions src/components/Comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ export default class Comment extends Component {
'复制'
];
let isLoginUser = currentUserId === userId;
if (!isLoginUser) {
// If userId is 0, it's anonymous user.
let canSendPrivateMessage = !isLoginUser && userId !== 0;
let editable =
isLoginUser && managePanel && managePanel.length > 0 && !!managePanel.find(item => item.title === '编辑');
if (canSendPrivateMessage) {
options.push('私信');
} else {
} else if (editable) {
options.push('编辑');
}
options.push('取消');
Expand Down Expand Up @@ -70,13 +74,11 @@ export default class Comment extends Component {
});
break;
case 2:
if (!isLoginUser) {
if (canSendPrivateMessage) {
navigation.navigate('PrivateMessage', { userId });
} else if (managePanel && managePanel.length > 0) {
} else if (editable) {
let editAction = managePanel.find(item => item.title === '编辑');
if (editAction) {
SafariView.show(editAction.action);
}
SafariView.show(editAction.action);
}
break;
}
Expand Down
Loading

0 comments on commit a44c826

Please sign in to comment.