mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-12 13:27:31 -08:00
fix(editor): Improve touch device detection (#9675)
This commit is contained in:
parent
dc17cf3a49
commit
3b86f52b02
|
@ -1,5 +1,11 @@
|
||||||
import { useDeviceSupport } from 'n8n-design-system/composables/useDeviceSupport';
|
import { useDeviceSupport } from 'n8n-design-system/composables/useDeviceSupport';
|
||||||
|
|
||||||
|
const detectPointerType = (query: string) => {
|
||||||
|
const isCoarse = query === '(any-pointer: coarse)';
|
||||||
|
const isFine = query === '(any-pointer: fine)';
|
||||||
|
return { fine: isFine, coarse: isCoarse };
|
||||||
|
};
|
||||||
|
|
||||||
describe('useDeviceSupport()', () => {
|
describe('useDeviceSupport()', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
global.window = Object.create(window);
|
global.window = Object.create(window);
|
||||||
|
@ -7,24 +13,38 @@ describe('useDeviceSupport()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isTouchDevice', () => {
|
describe('isTouchDevice', () => {
|
||||||
it('should be true if ontouchstart is in window', () => {
|
it('should be false if window matches `any-pointer: fine` and `!any-pointer: coarse`', () => {
|
||||||
Object.defineProperty(window, 'ontouchstart', {});
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
const { isTouchDevice } = useDeviceSupport();
|
value: vi.fn().mockImplementation((query: string) => {
|
||||||
expect(isTouchDevice).toEqual(true);
|
const { fine, coarse } = detectPointerType(query);
|
||||||
});
|
return { matches: fine && !coarse };
|
||||||
|
}),
|
||||||
it('should be true if navigator.maxTouchPoints > 0', () => {
|
});
|
||||||
Object.defineProperty(navigator, 'maxTouchPoints', { value: 1 });
|
|
||||||
const { isTouchDevice } = useDeviceSupport();
|
|
||||||
expect(isTouchDevice).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be false if no touch support', () => {
|
|
||||||
delete window.ontouchstart;
|
|
||||||
Object.defineProperty(navigator, 'maxTouchPoints', { value: 0 });
|
|
||||||
const { isTouchDevice } = useDeviceSupport();
|
const { isTouchDevice } = useDeviceSupport();
|
||||||
expect(isTouchDevice).toEqual(false);
|
expect(isTouchDevice).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be false if window matches `any-pointer: fine` and `any-pointer: coarse`', () => {
|
||||||
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
|
value: vi.fn().mockImplementation((query: string) => {
|
||||||
|
const { fine, coarse } = detectPointerType(query);
|
||||||
|
return { matches: fine && coarse };
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const { isTouchDevice } = useDeviceSupport();
|
||||||
|
expect(isTouchDevice).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be true if window matches `any-pointer: coarse` and `!any-pointer: fine`', () => {
|
||||||
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
|
value: vi.fn().mockImplementation((query: string) => {
|
||||||
|
const { fine, coarse } = detectPointerType(query);
|
||||||
|
return { matches: coarse && !fine };
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const { isTouchDevice } = useDeviceSupport();
|
||||||
|
expect(isTouchDevice).toEqual(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isMacOs', () => {
|
describe('isMacOs', () => {
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
export function useDeviceSupport() {
|
export function useDeviceSupport() {
|
||||||
const isTouchDevice = ref(window.hasOwnProperty('ontouchstart') || navigator.maxTouchPoints > 0);
|
/**
|
||||||
|
* Check if the device is a touch device but exclude devices that have a fine pointer (mouse or track-pad)
|
||||||
|
* - `fine` will check for an accurate pointing device. Examples include mice, touch-pads, and drawing styluses
|
||||||
|
* - `coarse` will check for a pointing device of limited accuracy. Examples include touchscreens and motion-detection sensors
|
||||||
|
* - `any-pointer` will check for the presence of any pointing device, if there are multiple of them
|
||||||
|
*/
|
||||||
|
const isTouchDevice = ref(
|
||||||
|
window.matchMedia('(any-pointer: coarse)').matches &&
|
||||||
|
!window.matchMedia('(any-pointer: fine)').matches,
|
||||||
|
);
|
||||||
const userAgent = ref(navigator.userAgent.toLowerCase());
|
const userAgent = ref(navigator.userAgent.toLowerCase());
|
||||||
const isMacOs = ref(
|
const isMacOs = ref(
|
||||||
userAgent.value.includes('macintosh') ||
|
userAgent.value.includes('macintosh') ||
|
||||||
|
|
|
@ -44,3 +44,18 @@ export class IntersectionObserver {
|
||||||
|
|
||||||
window.IntersectionObserver = IntersectionObserver;
|
window.IntersectionObserver = IntersectionObserver;
|
||||||
global.IntersectionObserver = IntersectionObserver;
|
global.IntersectionObserver = IntersectionObserver;
|
||||||
|
|
||||||
|
// Mocks for useDeviceSupport
|
||||||
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
|
writable: true,
|
||||||
|
value: vi.fn().mockImplementation((query) => ({
|
||||||
|
matches: true,
|
||||||
|
media: query,
|
||||||
|
onchange: null,
|
||||||
|
addListener: vi.fn(),
|
||||||
|
removeListener: vi.fn(),
|
||||||
|
addEventListener: vi.fn(),
|
||||||
|
removeEventListener: vi.fn(),
|
||||||
|
dispatchEvent: vi.fn(),
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue