Skip to content

Commit

Permalink
Merge pull request #2 from shalanah/halt-turning-anim-while-in-mobile…
Browse files Browse the repository at this point in the history
…-drawer

fix: halt turning milkcarton animation while in mobile drawer
  • Loading branch information
shalanah authored Mar 30, 2024
2 parents 8112c90 + a88a154 commit 7e8a7db
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 30 deletions.
5 changes: 5 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const inter = Inter_Tight({
});

// TODO: Move more over to metadata over putting in the head
// TODO: Figure out how to add viewport meta tag : see chrome issue : https://stackoverflow.com/a/77879573/2824643
export const metadata: Metadata = {
title: 'iOS404',
description: 'The missing web features of iOS',
Expand Down Expand Up @@ -57,6 +58,10 @@ export default function RootLayout({
property="og:image"
content="https://ios404.com/icons/ios-404-og-1200x630.jpg"
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<meta name="twitter:title" content="iOS404" />
<meta
name="twitter:description"
Expand Down
2 changes: 1 addition & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export default function Home() {
// Vertical View
if (width && width < verticalViewWidth) {
return (
<CanIUseContextProvider>
<CanIUseContextProvider verticalView>
<DarkModeProvider>
<GlobalCss />
<ErrorModal />
Expand Down
26 changes: 20 additions & 6 deletions src/components/experience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ const Button = styled.button`

const config = { mass: 0.05, tension: 600, friction: 40 };
export default function Experience() {
const { activeIndex, iOSMissingFeatures, setNextFeature, filteredData } =
useCanIUseContext();
const {
activeIndex,
iOSMissingFeatures,
setNextFeature,
filteredData,
doNotRotate,
} = useCanIUseContext();
const len = iOSMissingFeatures.length;
const filteredLen = filteredData.length;
const turns = useRef(0);
Expand All @@ -34,7 +39,7 @@ export default function Experience() {
// @ts-ignore
const prevPos = filteredData.findIndex((v) => v.index === prevActiveIndex);

if (activeIndex !== -1 && prevActiveIndex !== -1) {
if (activeIndex !== -1 && prevActiveIndex !== -1 && !doNotRotate) {
if (prevPos < pos) {
const looping = pos === filteredLen - 1 && prevPos === 0;
turns.current += looping ? -1 : 1;
Expand Down Expand Up @@ -87,8 +92,9 @@ export default function Experience() {
const value = Math.min(Math.abs(mx), 44.5); // clamping...
const sign = Math.sign(mx);
if (last) {
console.log({ value, filteredDatalength: filteredData.length });
if (value > 35 && filteredData.length > 1) {
setNextFeature({ forwards: sign === -1 });
setNextFeature({ forwards: sign === -1, action: 'swipe' });
return;
} else {
api.start({
Expand Down Expand Up @@ -155,7 +161,11 @@ export default function Experience() {
>
<Button
onClick={() =>
setNextFeature({ forwards: false, featureActive: false })
setNextFeature({
forwards: false,
featureActive: false,
action: 'arrows',
})
}
className="d-flex justify-content-center align-items-center justify-content-center"
>
Expand All @@ -177,7 +187,11 @@ export default function Experience() {
<Button
className="d-flex justify-content-center align-items-center"
onClick={() =>
setNextFeature({ forwards: true, featureActive: false })
setNextFeature({
forwards: true,
featureActive: false,
action: 'arrows',
})
}
>
<Arrow right />
Expand Down
4 changes: 1 addition & 3 deletions src/components/features.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use client';

import useCanIUseContext from '../hooks/useCanIUseContext';
import { buttonClass } from '../hooks/useCanIUseContext';
import styled from 'styled-components';
Expand Down Expand Up @@ -61,7 +59,7 @@ export default function Features() {
data-index={index} // to focus on load
className={buttonClass + (active ? ' active' : '')}
onClick={(e) => {
updateHash(key);
updateHash(key, 'button');
// Safari doesn't think buttons deserve focus... 🤷‍♀️?
// - https://stackoverflow.com/questions/42758815/safari-focus-event-doesnt-work-on-button-element
e.currentTarget.focus();
Expand Down
8 changes: 2 additions & 6 deletions src/components/filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,12 @@ const Error = styled.div`
`;

export const Filter = () => {
const { filters, iOSMissingFeatures, filteredData, loading } =
useCanIUseContext();
const { filters, filteredData, loading } = useCanIUseContext();
const len = Object.keys(filters.statuses).length;
const numChecked = Object.values(filters.statuses).filter((v) => v).length;
const filterCount = len - numChecked;

let count =
filteredData.length === iOSMissingFeatures.length
? `${iOSMissingFeatures.length} features`
: `${filteredData.length} features`;
let count = `${filteredData.length} features`;
if (loading) {
count = 'Loading...';
}
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useArrowKeysFeatureProgression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const useArrowKeysFeatureProgression = () => {
setNextFeature({
e,
forwards: ['ArrowDown', 'ArrowRight'].includes(e.key),
action: 'keys',
});
};
document.addEventListener('keyup', onKeyUp);
Expand Down
21 changes: 16 additions & 5 deletions src/hooks/useCanIUseContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import React, {
Dispatch,
SetStateAction,
} from 'react';
import { useHash } from './useHash';
import { ActionType, useHash } from './useHash';
import {
getIOSMissingFeatures,
IOSMissingFeaturesType,
Expand All @@ -19,11 +19,12 @@ import { useCanIUseData } from './useCanIUseData';
import { useFilters, type FiltersType } from './useFilters';
// import { parseMdnData } from '../utils/parseMdnData';

// TODO: Continue type checking + CLEANUP (more sharing of types)
interface CanIUseContextInterface {
loading: boolean;
hasError: boolean;
activeIndex: number;
updateHash: (newHash: string) => void;
updateHash: (newHash: string, action: ActionType) => void;
statuses: { [k: string]: string } | undefined;
filters: FiltersType;
setFilters: Dispatch<SetStateAction<FiltersType>>;
Expand All @@ -33,13 +34,16 @@ interface CanIUseContextInterface {
forwards: boolean;
e?: Event;
featureActive?: boolean;
action: ActionType;
}) => void;
canIUseDataUpdated: number | undefined;
setHasError: (error: boolean) => void;
iOSMissingFeatures: IOSMissingFeaturesType;
filteredData: IOSMissingFeaturesType;
filteredByBrowserOnly: IOSMissingFeaturesType;
activeInFilteredData: boolean;
actionType: ActionType;
doNotRotate: boolean;
}

// Game state... could probably be broken out into smaller files / hooks
Expand All @@ -50,8 +54,10 @@ export const buttonClass = 'feature-list-button';

// TODO: Separate out some of these providers?
export const CanIUseContextProvider = ({
verticalView = false,
children,
}: {
verticalView?: boolean;
children: ReactNode;
}) => {
const { canIUseData, loading, hasError, setHasError } = useCanIUseData();
Expand All @@ -61,7 +67,7 @@ export const CanIUseContextProvider = ({
);
const [search, setSearch] = useState('');
const [filters, setFilters] = useFilters();
const [hash, updateHash] = useHash();
const { hash, updateHash, actionType } = useHash();

let activeIndex =
iOSMissingFeatures.length > 0
Expand All @@ -77,7 +83,7 @@ export const CanIUseContextProvider = ({
activeIndex !== -1 &&
hash !== iOSMissingFeatures[activeIndex]?.key
) {
updateHash('');
updateHash('', 'load');
}
}, [updateHash, activeIndex, iOSMissingFeatures, hash]);

Expand All @@ -102,14 +108,17 @@ export const CanIUseContextProvider = ({
});
}

// useCallback?
const setNextFeature = ({
forwards,
e,
featureActive = true,
action,
}: {
forwards: boolean;
e?: Event;
featureActive?: boolean;
action: ActionType;
}) => {
const len = filteredData.length;
if (len < 1) return;
Expand All @@ -122,7 +131,7 @@ export const CanIUseContextProvider = ({
}
if (e) e.preventDefault(); // prevent scrolling down
const { key, index } = filteredData[filteredIndex];
updateHash(key);
updateHash(key, action);
const el = document.querySelector(`.${buttonClass}[data-index="${index}"]`);
if (featureActive) {
if (el) (el as HTMLElement).focus(); // scroll ino view
Expand Down Expand Up @@ -169,6 +178,8 @@ export const CanIUseContextProvider = ({
canIUseDataUpdated: canIUseData?.updated,
setHasError,
activeInFilteredData: filteredData.some((v) => v.index === activeIndex),
actionType,
doNotRotate: verticalView && actionType === 'button', // too distracting with drawer open
}}
>
{children}
Expand Down
28 changes: 19 additions & 9 deletions src/hooks/useHash.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { useEffect, useCallback, useState, use } from 'react';
import { useEffect, useCallback, useState } from 'react';

// Source: https://www.30secondsofcode.org/react/s/use-hash/
export const useHash = (): [string, (newHash: string) => void] => {
const [hash, setHash] = useState<string>(() => window.location.hash);
export type ActionType = 'button' | 'load' | 'arrows' | 'keys' | 'swipe';
type HashType = string;

// Inspiration: https://www.30secondsofcode.org/react/s/use-hash/
export const useHash = () => {
const [{ hash, actionType }, setHash] = useState<{
hash: HashType;
actionType: ActionType;
}>(() => {
return {
hash: window?.location?.hash || '',
actionType: 'load',
};
});

const hashChangeHandler = useCallback(() => {
setHash(window.location.hash);
setHash({ hash: window?.location?.hash || '', actionType: 'load' });
}, []);

useEffect(() => {
window.addEventListener('hashchange', hashChangeHandler);
return () => {
Expand All @@ -16,15 +26,15 @@ export const useHash = (): [string, (newHash: string) => void] => {
}, [hashChangeHandler]);

const updateHash = useCallback(
(newHash: string) => {
(newHash: HashType, action: ActionType) => {
if (newHash !== hash) {
const urlWithoutHash = window.location.href.split('#')[0];
window.history.replaceState(null, '', `${urlWithoutHash}#${newHash}`);
setHash(`#${newHash}`);
setHash({ hash: `#${newHash}`, actionType: action });
}
},
[hash]
);

return [hash.slice(1), updateHash];
return { hash: hash.slice(1), updateHash, actionType };
};

0 comments on commit 7e8a7db

Please sign in to comment.