feat: pull down to refresh (#2908)

* feat: pull down to refresh functionality

Custom pull down to refresh added to replace the default browser pull down to refresh. This will
allow you to manually reload the page if you are using it as a PWA.

* test: update test to check api call correctly

changed api call for test and made sure it pulls down all the way to trigger refresh

* fix: changed positioning of pull to refresh

Refresh indicator now has absolute positioning and will prevent the top edge from pulling down.
This commit is contained in:
Brandon Cohen
2022-09-11 22:07:37 -04:00
committed by GitHub
parent 99fc9a2da0
commit 87825a0e05
7 changed files with 102 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
describe('Pull To Refresh', () => {
beforeEach(() => {
cy.login(Cypress.env('ADMIN_EMAIL'), Cypress.env('ADMIN_PASSWORD'));
cy.viewport(390, 844);
cy.visitMobile('/');
});
it('reloads the current page', () => {
cy.wait(500);
cy.intercept({
method: 'GET',
url: '/api/v1/*',
}).as('apiCall');
cy.get('.searchbar').swipe('bottom', [190, 400]);
cy.wait('@apiCall').then((interception) => {
assert.isNotNull(
interception.response.body,
'API was called and received data'
);
});
});
});

View File

@@ -1,4 +1,5 @@
/// <reference types="cypress" />
import 'cy-mobile-commands';
Cypress.Commands.add('login', (email, password) => {
cy.session(

View File

@@ -67,6 +67,7 @@
"openpgp": "5.4.0",
"plex-api": "5.3.2",
"pug": "3.0.2",
"pulltorefreshjs": "0.1.22",
"react": "18.2.0",
"react-ace": "10.1.0",
"react-animate-height": "2.1.2",
@@ -116,6 +117,7 @@
"@types/node": "17.0.36",
"@types/node-schedule": "2.1.0",
"@types/nodemailer": "6.4.5",
"@types/pulltorefreshjs": "0.1.5",
"@types/react": "18.0.17",
"@types/react-dom": "18.0.6",
"@types/react-transition-group": "4.4.5",
@@ -133,6 +135,7 @@
"babel-plugin-react-intl-auto": "3.3.0",
"commitizen": "4.2.5",
"copyfiles": "2.4.1",
"cy-mobile-commands": "0.3.0",
"cypress": "10.6.0",
"cz-conventional-changelog": "3.3.0",
"eslint": "8.22.0",

View File

@@ -1,6 +1,7 @@
import SearchInput from '@app/components/Layout/SearchInput';
import Sidebar from '@app/components/Layout/Sidebar';
import UserDropdown from '@app/components/Layout/UserDropdown';
import PullToRefresh from '@app/components/PullToRefresh';
import type { AvailableLocale } from '@app/context/LanguageContext';
import useLocale from '@app/hooks/useLocale';
import useSettings from '@app/hooks/useSettings';
@@ -57,6 +58,7 @@ const Layout = ({ children }: LayoutProps) => {
<Sidebar open={isSidebarOpen} setClosed={() => setSidebarOpen(false)} />
<div className="relative mb-16 flex w-0 min-w-0 flex-1 flex-col lg:ml-64">
<PullToRefresh />
<div
className={`searchbar fixed left-0 right-0 top-0 z-10 flex flex-shrink-0 bg-opacity-80 transition duration-300 ${
isScrolled ? 'bg-gray-700' : 'bg-transparent'

View File

@@ -0,0 +1,36 @@
import { RefreshIcon } from '@heroicons/react/outline';
import Router from 'next/router';
import PR from 'pulltorefreshjs';
import { useEffect } from 'react';
import ReactDOMServer from 'react-dom/server';
const PullToRefresh: React.FC = () => {
useEffect(() => {
PR.init({
mainElement: '#pull-to-refresh',
onRefresh() {
Router.reload();
},
iconArrow: ReactDOMServer.renderToString(
<RefreshIcon className="z-50 m-auto h-9 w-9 rounded-full border-4 border-gray-800 bg-gray-800 text-indigo-500 ring-1 ring-gray-700" />
),
iconRefreshing: ReactDOMServer.renderToString(
<RefreshIcon
className="z-50 m-auto h-9 w-9 animate-spin rounded-full border-4 border-gray-800 bg-gray-800 text-indigo-500 ring-1 ring-gray-700"
style={{ animationDirection: 'reverse' }}
/>
),
instructionsPullToRefresh: ReactDOMServer.renderToString(<div />),
instructionsReleaseToRefresh: ReactDOMServer.renderToString(<div />),
instructionsRefreshing: ReactDOMServer.renderToString(<div />),
distReload: 55,
});
return () => {
PR.destroyAll();
};
}, []);
return <div id="pull-to-refresh"></div>;
};
export default PullToRefresh;

View File

@@ -11,6 +11,7 @@
body {
@apply bg-gray-900;
overscroll-behavior-y: contain;
}
code {
@@ -453,3 +454,22 @@
}
}
}
.ptr--ptr {
box-shadow: initial !important;
position: absolute !important;
z-index: 30 !important;
}
.ptr--refresh {
overflow: visible !important;
z-index: 30 !important;
}
.ptr--pull {
z-index: 30 !important;
}
.ptr--ptr .ptr--box {
margin-bottom: -13px !important;
}

View File

@@ -3047,6 +3047,11 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
"@types/pulltorefreshjs@0.1.5":
version "0.1.5"
resolved "https://registry.yarnpkg.com/@types/pulltorefreshjs/-/pulltorefreshjs-0.1.5.tgz#f15c9dbc91b8fdd8135093d81ece9e9d4d2324d7"
integrity sha512-/VRTgBettvBg1KI8mGnA9oeWs359tTXQ7qsxLuXnksL88jvK6ZNMStG5T9x9vUO9O7jLsgREB0cElz/BWFfdew==
"@types/qs@*":
version "6.9.7"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
@@ -4942,6 +4947,11 @@ csurf@1.11.0:
csrf "3.1.0"
http-errors "~1.7.3"
cy-mobile-commands@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/cy-mobile-commands/-/cy-mobile-commands-0.3.0.tgz#2bf242093149154d846b755977da197b4730429e"
integrity sha512-Bj5P2ylw88hPqolLu68xWB6euVH5uNt8zyh+Ju8sBukGv39mWZxpjp6LtnUX/LK/YMthwvILYHhvr9SG1TP+4w==
cypress@10.6.0:
version "10.6.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.6.0.tgz#13f46867febf2c3715874ed5dce9c2e946b175fe"
@@ -10157,6 +10167,11 @@ pug@3.0.2, pug@^3.0.2:
pug-runtime "^3.0.1"
pug-strip-comments "^2.0.0"
pulltorefreshjs@0.1.22:
version "0.1.22"
resolved "https://registry.yarnpkg.com/pulltorefreshjs/-/pulltorefreshjs-0.1.22.tgz#ddb5e3feee0b2a49fd46e1b18e84fffef2c47ac0"
integrity sha512-haxNVEHnS4NCQA7NeG7TSV69z4uqy/N7nfPRuc4dPWe8H6ygUrMjdNeohE+6v0lVVX/ukSjbLYwPUGUYtFKfvQ==
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"