Skip to content

Commit

Permalink
feat: tab swiping (#1656)
Browse files Browse the repository at this point in the history
  • Loading branch information
StarScape authored Mar 22, 2024
1 parent 59665ff commit a534b29
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ app.

## [Unreleased]

- Made it possible to change tabs in the popup by swiping horizontally
thanks to [@StarScape](https://github.com/StarScape)
([#1656](https://github.com/birchill/10ten-ja-reader/issues/1656)).
- Made copying to the clipboard include rare headwords again when not using
simplified copy mode
([#1665](https://github.com/birchill/10ten-ja-reader/issues/1665)).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
- [Installing](#installing)
- [Features](#features)
- [Usage](#usage)
- [Building from source](#building-from-source)
- [Building from source](#building-a-release-from-source)
- [Contributing](#contributing)
- [Contributors](#contributors)

Expand Down
26 changes: 22 additions & 4 deletions src/content/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2057,19 +2057,19 @@ export class ContentHandler {
}

showDictionary(
dictToShow: 'next' | MajorDataSeries,
dictToShow: 'next' | 'prev' | MajorDataSeries,
options: { fixPopupPosition?: boolean } = {}
) {
if (!this.currentSearchResult) {
return;
}

let dict: MajorDataSeries;
const cycleOrder: Array<MajorDataSeries> = ['words', 'kanji', 'names'];

if (dictToShow == 'next') {
if (dictToShow === 'next') {
dict = this.currentDict;

const cycleOrder: Array<MajorDataSeries> = ['words', 'kanji', 'names'];
let next = (cycleOrder.indexOf(this.currentDict) + 1) % cycleOrder.length;
while (cycleOrder[next] !== this.currentDict) {
const nextDict = cycleOrder[next];
Expand All @@ -2082,6 +2082,24 @@ export class ContentHandler {
}
next = ++next % cycleOrder.length;
}
} else if (dictToShow === 'prev') {
dict = this.currentDict;

let prev = mod(
cycleOrder.indexOf(this.currentDict) - 1,
cycleOrder.length
);
while (cycleOrder[prev] !== this.currentDict) {
const prevDict = cycleOrder[prev];
if (
this.currentSearchResult[prevDict] ||
(prevDict === 'words' && !!this.currentLookupParams?.meta)
) {
dict = prevDict;
break;
}
prev = mod(--prev, cycleOrder.length);
}
} else {
dict = dictToShow;
}
Expand Down Expand Up @@ -2207,7 +2225,7 @@ export class ContentHandler {
// Ignore
});
},
onSwitchDictionary: (dict: MajorDataSeries) => {
onSwitchDictionary: (dict: MajorDataSeries | 'next' | 'prev') => {
this.showDictionary(dict, { fixPopupPosition: true });
},
onTogglePin: () => {
Expand Down
10 changes: 7 additions & 3 deletions src/content/popup/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { renderKanjiEntries } from './kanji';
import { renderMetadata } from './metadata';
import { renderNamesEntries } from './names';
import { renderCopyDetails, renderUpdatingStatus } from './status';
import { onHorizontalSwipe } from './swipe';
import { renderTabBar } from './tabs';
import { renderWordEntries } from './words';

Expand Down Expand Up @@ -69,7 +70,7 @@ export interface PopupOptions {
onClosePopup?: () => void;
onExpandPopup?: () => void;
onShowSettings?: () => void;
onSwitchDictionary?: (newDict: MajorDataSeries) => void;
onSwitchDictionary?: (newDict: MajorDataSeries | 'next' | 'prev') => void;
onTogglePin?: () => void;
pinShortcuts?: ReadonlyArray<string>;
posDisplay: PartOfSpeechDisplay;
Expand All @@ -93,6 +94,7 @@ export function renderPopup(
fontSize: options.fontSize || 'normal',
popupStyle: options.popupStyle,
});
const contentContainer = html('div', { class: 'content' });

const hasResult = result && (result.words || result.kanji || result.names);
const showTabs =
Expand Down Expand Up @@ -123,9 +125,11 @@ export function renderPopup(
);

windowElem.dataset.tabSide = options.tabDisplay || 'top';
}

const contentContainer = html('div', { class: 'content' });
onHorizontalSwipe(contentContainer, (direction) => {
options.onSwitchDictionary?.(direction === 'left' ? 'prev' : 'next');
});
}

const resultToShow = result?.[options.dictToShow];

Expand Down
58 changes: 58 additions & 0 deletions src/content/popup/swipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
type HorizontalSwipeDirection = 'right' | 'left';

export function onHorizontalSwipe(
element: HTMLElement,
handler: (swipeDirection: HorizontalSwipeDirection) => void
) {
// Min x distance traveled to be considered swipe
const xMinThreshold = 50;
// Max y distance that can be traveled before
// it's no longer considered a horizontal swipe
const yMaxThreshold = 100;
// Max time allowed to travel that distance
const allowedTime = 200;

let startTime = 0;
let startX: number;
let startY: number;

element.addEventListener(
'touchstart',
function (e) {
startX = e.changedTouches[0].pageX;
startY = e.changedTouches[0].pageY;
startTime = performance.now();
},
false
);

element.addEventListener(
'touchmove',
function (e) {
// Prevent dragging viewport
e.preventDefault();
},
false
);

element.addEventListener(
'touchend',
function (e) {
const touch = e.changedTouches[0];
const deltaX = touch.pageX - startX;
const deltaY = touch.pageY - startY;
const elapsedTime = performance.now() - startTime;

// Check that elapsed time is within specified, horizontal dist
// traveled >= threshold, and vertical dist traveled <= 100
const isSwipe =
elapsedTime <= allowedTime &&
Math.abs(deltaX) >= xMinThreshold &&
Math.abs(deltaY) <= yMaxThreshold;
if (isSwipe) {
handler(deltaX < 0 ? 'right' : 'left');
}
},
false
);
}

0 comments on commit a534b29

Please sign in to comment.