diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2020-02-15 15:59:26 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2020-02-18 15:29:44 +0100 |
| commit | 9f850da5dcafff368604914aff683a20cb502f94 (patch) | |
| tree | 3ea724b403b1115bcda1a88642c53886f06bab54 /gui/src/renderer/components | |
| parent | 96a7d0901901dec6b7b3dcc7c5e3d205992aebdd (diff) | |
| download | mullvadvpn-9f850da5dcafff368604914aff683a20cb502f94.tar.xz mullvadvpn-9f850da5dcafff368604914aff683a20cb502f94.zip | |
Display long location names on one line
Diffstat (limited to 'gui/src/renderer/components')
| -rw-r--r-- | gui/src/renderer/components/Marquee.tsx | 63 | ||||
| -rw-r--r-- | gui/src/renderer/components/TunnelControl.tsx | 9 |
2 files changed, 69 insertions, 3 deletions
diff --git a/gui/src/renderer/components/Marquee.tsx b/gui/src/renderer/components/Marquee.tsx new file mode 100644 index 0000000000..23fa7d6dcd --- /dev/null +++ b/gui/src/renderer/components/Marquee.tsx @@ -0,0 +1,63 @@ +import * as React from 'react'; +import { Animated, Component, Styles, Types, UserInterface, View } from 'reactxp'; + +const styles = { + text: Styles.createTextStyle({ + // @ts-ignore + width: 'fit-content', + whiteSpace: 'nowrap', + }), +}; + +interface IMarqueeProps { + style?: Types.StyleRuleSetRecursive<Types.ButtonStyleRuleSet>; +} + +export default class Marquee extends Component<IMarqueeProps> { + private initialLeft = Animated.createValue(0.0); + private textAnimation = Styles.createAnimatedTextStyle({ left: this.initialLeft }); + private textRef = React.createRef<Animated.Text>(); + + public componentDidMount() { + this.startAnimation(); + } + + public componentDidUpdate() { + this.startAnimation(); + } + + public render() { + return ( + <View> + <Animated.Text + ref={this.textRef} + style={[styles.text, this.textAnimation, this.props.style]}> + {this.props.children} + </Animated.Text> + </View> + ); + } + + private async startAnimation() { + setTimeout(async () => { + if (this.textRef.current) { + const textLayout = await UserInterface.measureLayoutRelativeToWindow(this.textRef.current); + const viewLayout = await UserInterface.measureLayoutRelativeToWindow(this); + this.startAnimationImpl(textLayout.width - viewLayout.width, false); + } + }, 1000); + } + + private startAnimationImpl(length: number, reverse: boolean) { + if (length >= 0) { + Animated.timing(this.initialLeft, { + toValue: reverse ? 0.0 : -length, + duration: length * 80, + delay: 2000, + easing: Animated.Easing.Linear(), + }).start(() => { + this.startAnimationImpl(length, !reverse); + }); + } + } +} diff --git a/gui/src/renderer/components/TunnelControl.tsx b/gui/src/renderer/components/TunnelControl.tsx index eba2a3190b..d8a5937760 100644 --- a/gui/src/renderer/components/TunnelControl.tsx +++ b/gui/src/renderer/components/TunnelControl.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; -import { Component, Styles, Text, Types, View } from 'reactxp'; +import { Component, Styles, Types, View } from 'reactxp'; import { colors } from '../../config.json'; import { TunnelState } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import ConnectionPanelContainer from '../containers/ConnectionPanelContainer'; import * as AppButton from './AppButton'; import ImageView from './ImageView'; +import Marquee from './Marquee'; import { IMainButtonProps, ISideButtonProps, MultiButton } from './MultiButton'; import SecuredLabel, { SecuredDisplayStyle } from './SecuredLabel'; @@ -68,8 +69,10 @@ export default class TunnelControl extends Component<ITunnelControlProps> { const Location = ({ children }: { children?: React.ReactNode }) => ( <View style={styles.status_location}>{children}</View> ); - const City = () => <Text style={styles.status_location_text}>{this.props.city}</Text>; - const Country = () => <Text style={styles.status_location_text}>{this.props.country}</Text>; + const City = () => <Marquee style={styles.status_location_text}>{this.props.city}</Marquee>; + const Country = () => ( + <Marquee style={styles.status_location_text}>{this.props.country}</Marquee> + ); const SwitchLocation = () => { return ( |
