This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
7.3 KiB
251 lines
7.3 KiB
/** |
|
* Copyright (c) 2013-present, Facebook, Inc. |
|
* |
|
* This source code is licensed under the MIT license found in the |
|
* LICENSE file in the root directory of this source tree. |
|
* |
|
* @providesModule ViewPagerAndroid |
|
* @flow |
|
*/ |
|
'use strict'; |
|
|
|
const React = require('React'); |
|
const PropTypes = require('prop-types'); |
|
const ReactNative = require('ReactNative'); |
|
const UIManager = require('UIManager'); |
|
const ViewPropTypes = require('ViewPropTypes'); |
|
|
|
const dismissKeyboard = require('dismissKeyboard'); |
|
const requireNativeComponent = require('requireNativeComponent'); |
|
|
|
const VIEWPAGER_REF = 'viewPager'; |
|
|
|
type Event = Object; |
|
|
|
export type ViewPagerScrollState = $Enum<{ |
|
idle: string, |
|
dragging: string, |
|
settling: string, |
|
}>; |
|
|
|
/** |
|
* Container that allows to flip left and right between child views. Each |
|
* child view of the `ViewPagerAndroid` will be treated as a separate page |
|
* and will be stretched to fill the `ViewPagerAndroid`. |
|
* |
|
* It is important all children are `<View>`s and not composite components. |
|
* You can set style properties like `padding` or `backgroundColor` for each |
|
* child. It is also important that each child have a `key` prop. |
|
* |
|
* Example: |
|
* |
|
* ``` |
|
* render: function() { |
|
* return ( |
|
* <ViewPagerAndroid |
|
* style={styles.viewPager} |
|
* initialPage={0}> |
|
* <View style={styles.pageStyle} key="1"> |
|
* <Text>First page</Text> |
|
* </View> |
|
* <View style={styles.pageStyle} key="2"> |
|
* <Text>Second page</Text> |
|
* </View> |
|
* </ViewPagerAndroid> |
|
* ); |
|
* } |
|
* |
|
* ... |
|
* |
|
* var styles = { |
|
* ... |
|
* viewPager: { |
|
* flex: 1 |
|
* }, |
|
* pageStyle: { |
|
* alignItems: 'center', |
|
* padding: 20, |
|
* } |
|
* } |
|
* ``` |
|
*/ |
|
class ViewPagerAndroid extends React.Component<{ |
|
initialPage?: number, |
|
onPageScroll?: Function, |
|
onPageScrollStateChanged?: Function, |
|
onPageSelected?: Function, |
|
pageMargin?: number, |
|
peekEnabled?: boolean, |
|
keyboardDismissMode?: 'none' | 'on-drag', |
|
scrollEnabled?: boolean, |
|
}> { |
|
static propTypes = { |
|
...ViewPropTypes, |
|
/** |
|
* Index of initial page that should be selected. Use `setPage` method to |
|
* update the page, and `onPageSelected` to monitor page changes |
|
*/ |
|
initialPage: PropTypes.number, |
|
|
|
/** |
|
* Executed when transitioning between pages (ether because of animation for |
|
* the requested page change or when user is swiping/dragging between pages) |
|
* The `event.nativeEvent` object for this callback will carry following data: |
|
* - position - index of first page from the left that is currently visible |
|
* - offset - value from range [0,1) describing stage between page transitions. |
|
* Value x means that (1 - x) fraction of the page at "position" index is |
|
* visible, and x fraction of the next page is visible. |
|
*/ |
|
onPageScroll: PropTypes.func, |
|
|
|
/** |
|
* Function called when the page scrolling state has changed. |
|
* The page scrolling state can be in 3 states: |
|
* - idle, meaning there is no interaction with the page scroller happening at the time |
|
* - dragging, meaning there is currently an interaction with the page scroller |
|
* - settling, meaning that there was an interaction with the page scroller, and the |
|
* page scroller is now finishing it's closing or opening animation |
|
*/ |
|
onPageScrollStateChanged: PropTypes.func, |
|
|
|
/** |
|
* This callback will be called once ViewPager finish navigating to selected page |
|
* (when user swipes between pages). The `event.nativeEvent` object passed to this |
|
* callback will have following fields: |
|
* - position - index of page that has been selected |
|
*/ |
|
onPageSelected: PropTypes.func, |
|
|
|
/** |
|
* Blank space to show between pages. This is only visible while scrolling, pages are still |
|
* edge-to-edge. |
|
*/ |
|
pageMargin: PropTypes.number, |
|
|
|
/** |
|
* Determines whether the keyboard gets dismissed in response to a drag. |
|
* - 'none' (the default), drags do not dismiss the keyboard. |
|
* - 'on-drag', the keyboard is dismissed when a drag begins. |
|
*/ |
|
keyboardDismissMode: PropTypes.oneOf([ |
|
'none', // default |
|
'on-drag', |
|
]), |
|
|
|
/** |
|
* When false, the content does not scroll. |
|
* The default value is true. |
|
*/ |
|
scrollEnabled: PropTypes.bool, |
|
|
|
/** |
|
* Whether enable showing peekFraction or not. If this is true, the preview of |
|
* last and next page will show in current screen. Defaults to false. |
|
*/ |
|
peekEnabled: PropTypes.bool, |
|
}; |
|
|
|
componentDidMount() { |
|
if (this.props.initialPage != null) { |
|
this.setPageWithoutAnimation(this.props.initialPage); |
|
} |
|
} |
|
|
|
getInnerViewNode = (): ReactComponent => { |
|
return this.refs[VIEWPAGER_REF].getInnerViewNode(); |
|
}; |
|
|
|
_childrenWithOverridenStyle = (): Array => { |
|
// Override styles so that each page will fill the parent. Native component |
|
// will handle positioning of elements, so it's not important to offset |
|
// them correctly. |
|
return React.Children.map(this.props.children, function(child) { |
|
if (!child) { |
|
return null; |
|
} |
|
const newProps = { |
|
...child.props, |
|
style: [child.props.style, { |
|
position: 'absolute', |
|
left: 0, |
|
top: 0, |
|
right: 0, |
|
bottom: 0, |
|
width: undefined, |
|
height: undefined, |
|
}], |
|
collapsable: false, |
|
}; |
|
if (child.type && |
|
child.type.displayName && |
|
(child.type.displayName !== 'RCTView') && |
|
(child.type.displayName !== 'View')) { |
|
console.warn('Each ViewPager child must be a <View>. Was ' + child.type.displayName); |
|
} |
|
return React.createElement(child.type, newProps); |
|
}); |
|
}; |
|
|
|
_onPageScroll = (e: Event) => { |
|
if (this.props.onPageScroll) { |
|
this.props.onPageScroll(e); |
|
} |
|
if (this.props.keyboardDismissMode === 'on-drag') { |
|
dismissKeyboard(); |
|
} |
|
}; |
|
|
|
_onPageScrollStateChanged = (e: Event) => { |
|
if (this.props.onPageScrollStateChanged) { |
|
this.props.onPageScrollStateChanged(e.nativeEvent.pageScrollState); |
|
} |
|
}; |
|
|
|
_onPageSelected = (e: Event) => { |
|
if (this.props.onPageSelected) { |
|
this.props.onPageSelected(e); |
|
} |
|
}; |
|
|
|
/** |
|
* A helper function to scroll to a specific page in the ViewPager. |
|
* The transition between pages will be animated. |
|
*/ |
|
setPage = (selectedPage: number) => { |
|
UIManager.dispatchViewManagerCommand( |
|
ReactNative.findNodeHandle(this), |
|
UIManager.AndroidViewPager.Commands.setPage, |
|
[selectedPage], |
|
); |
|
}; |
|
|
|
/** |
|
* A helper function to scroll to a specific page in the ViewPager. |
|
* The transition between pages will *not* be animated. |
|
*/ |
|
setPageWithoutAnimation = (selectedPage: number) => { |
|
UIManager.dispatchViewManagerCommand( |
|
ReactNative.findNodeHandle(this), |
|
UIManager.AndroidViewPager.Commands.setPageWithoutAnimation, |
|
[selectedPage], |
|
); |
|
}; |
|
|
|
render() { |
|
return ( |
|
<NativeAndroidViewPager |
|
{...this.props} |
|
ref={VIEWPAGER_REF} |
|
style={this.props.style} |
|
onPageScroll={this._onPageScroll} |
|
onPageScrollStateChanged={this._onPageScrollStateChanged} |
|
onPageSelected={this._onPageSelected} |
|
children={this._childrenWithOverridenStyle()} |
|
/> |
|
); |
|
} |
|
} |
|
|
|
const NativeAndroidViewPager = requireNativeComponent('AndroidViewPager', ViewPagerAndroid); |
|
|
|
module.exports = ViewPagerAndroid;
|
|
|