From c57d50aa4e7cd83a07d5b9f97f17856d90e80e2d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 2 Dec 2021 14:11:40 -0600 Subject: [PATCH 1/2] PullToRefresh: increase pull resistance and threshold --- app/soapbox/components/pull_to_refresh.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/soapbox/components/pull_to_refresh.js b/app/soapbox/components/pull_to_refresh.js index 6d315e687..9ff1e6c88 100644 --- a/app/soapbox/components/pull_to_refresh.js +++ b/app/soapbox/components/pull_to_refresh.js @@ -33,6 +33,9 @@ export default class PullToRefresh extends React.Component { pullingContent={null} // `undefined` will fallback to the default, while `null` will render nothing refreshingContent={onRefresh ? undefined : null} + pullDownThreshold={130} + maxPullDownDistance={130} + resistance={2} {...rest} > {children} From d6bc8d8b6ceaf6aa376023c14e5091217ce69eee Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 2 Dec 2021 15:03:52 -0600 Subject: [PATCH 2/2] PullToRefresh: use iOS style spinner --- app/soapbox/components/loading_spinner.js | 20 ++++ app/soapbox/components/pull_to_refresh.js | 7 +- app/styles/loading.scss | 111 ++++++++++++++++++++++ 3 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 app/soapbox/components/loading_spinner.js diff --git a/app/soapbox/components/loading_spinner.js b/app/soapbox/components/loading_spinner.js new file mode 100644 index 000000000..a632454db --- /dev/null +++ b/app/soapbox/components/loading_spinner.js @@ -0,0 +1,20 @@ +/** + * iOS style loading spinner. + * It's mostly CSS, adapted from: https://loading.io/css/ + */ +import React from 'react'; +import PropTypes from 'prop-types'; + +const LoadingSpinner = ({ size = 30 }) => ( +
+ {Array(12).fill().map(i => ( +
+ ))} +
+); + +LoadingSpinner.propTypes = { + size: PropTypes.number, +}; + +export default LoadingSpinner; diff --git a/app/soapbox/components/pull_to_refresh.js b/app/soapbox/components/pull_to_refresh.js index 9ff1e6c88..f138e14ae 100644 --- a/app/soapbox/components/pull_to_refresh.js +++ b/app/soapbox/components/pull_to_refresh.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import PTRComponent from 'react-simple-pull-to-refresh'; +import LoadingSpinner from 'soapbox/components/loading_spinner'; /** * PullToRefresh: @@ -32,9 +33,9 @@ export default class PullToRefresh extends React.Component { onRefresh={this.handleRefresh} pullingContent={null} // `undefined` will fallback to the default, while `null` will render nothing - refreshingContent={onRefresh ? undefined : null} - pullDownThreshold={130} - maxPullDownDistance={130} + refreshingContent={onRefresh ? : null} + pullDownThreshold={67} + maxPullDownDistance={95} resistance={2} {...rest} > diff --git a/app/styles/loading.scss b/app/styles/loading.scss index c26ec70fe..b893128ae 100644 --- a/app/styles/loading.scss +++ b/app/styles/loading.scss @@ -229,3 +229,114 @@ .ptr__children { overflow: visible !important; } + +.ptr .lds-spinner { + width: 40px; + height: 40px; +} + +.ptr__pull-down { + transform: translateY(10px); +} + +/** + * iOS style loading spinner. + * Adapted from: https://loading.io/css/ + * With some help scaling it: https://signalvnoise.com/posts/2577-loading-spinner-animation-using-css-and-webkit + */ +.lds-spinner { + display: inline-block; + position: relative; + width: 80px; + height: 80px; + + div { + position: absolute; + transform-origin: 50% 50%; + animation: lds-spinner 1.2s linear infinite; + width: 100%; + height: 100%; + + &::after { + content: ' '; + display: block; + position: absolute; + top: 3.75%; + left: 46.25%; + width: 7.5%; + height: 22.5%; + border-radius: 20%; + background: var(--primary-text-color); + } + + &:nth-child(1) { + transform: rotate(0deg); + animation-delay: -1.1s; + } + + &:nth-child(2) { + transform: rotate(30deg); + animation-delay: -1s; + } + + &:nth-child(3) { + transform: rotate(60deg); + animation-delay: -0.9s; + } + + &:nth-child(4) { + transform: rotate(90deg); + animation-delay: -0.8s; + } + + &:nth-child(5) { + transform: rotate(120deg); + animation-delay: -0.7s; + } + + &:nth-child(6) { + transform: rotate(150deg); + animation-delay: -0.6s; + } + + &:nth-child(7) { + transform: rotate(180deg); + animation-delay: -0.5s; + } + + &:nth-child(8) { + transform: rotate(210deg); + animation-delay: -0.4s; + } + + &:nth-child(9) { + transform: rotate(240deg); + animation-delay: -0.3s; + } + + &:nth-child(10) { + transform: rotate(270deg); + animation-delay: -0.2s; + } + + &:nth-child(11) { + transform: rotate(300deg); + animation-delay: -0.1s; + } + + &:nth-child(12) { + transform: rotate(330deg); + animation-delay: 0s; + } + } +} + +@keyframes lds-spinner { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +}