Merge branch 'fix-swipe-menu-bugs' into 'main'

Display Bug Fixes

See merge request walljm/dynamicbible!16
This commit is contained in:
Jason Wall 2021-04-12 22:44:37 +00:00
commit 743dbd4199
7 changed files with 97 additions and 66 deletions

View File

@ -13,7 +13,6 @@
"serverClientId": "200739882604-i4mk6rp4mcb8n590j5kc8i6bncpm5bo1.apps.googleusercontent.com", "serverClientId": "200739882604-i4mk6rp4mcb8n590j5kc8i6bncpm5bo1.apps.googleusercontent.com",
"forceCodeForRefreshToken" : true "forceCodeForRefreshToken" : true
} }
}, },
"cordova": {} "cordova": {}
} }

View File

@ -11,8 +11,10 @@
(cdkDropListDropped)="moveSavedPageCard($event)" (cdkDropListDropped)="moveSavedPageCard($event)"
> >
<div class="card-item" cdkDrag *ngFor="let q of savedPage.queries"> <div class="card-item" cdkDrag *ngFor="let q of savedPage.queries">
<div class="drag-handle" cdkDragHandle>
<span matLine><mat-icon class="page_item_icon" [ngClass]="class(q)">{{ icons(q) }}</mat-icon>{{ format(q) }}</span> <mat-icon>drag_handle</mat-icon>
</div>
<span class="item-title" matLine><mat-icon class="page_item_icon" [ngClass]="class(q)">{{ icons(q) }}</mat-icon>{{ format(q) }}</span>
<button mat-icon-button (click)="onRemoveCard(q)"> <button mat-icon-button (click)="onRemoveCard(q)">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
</button> </button>

View File

@ -3,8 +3,7 @@
} }
.page_item_icon { .page_item_icon {
vertical-align: text-bottom; margin-right: .8rem;
margin-right: 3px;
} }
.card-actions { .card-actions {
color: var(--page-color-primary); color: var(--page-color-primary);
@ -26,6 +25,14 @@
color: var(--note-color-primary); color: var(--note-color-primary);
} }
.drag-handle {
cursor: move;
display: inline-block;
width: 3rem;
text-align: center;
margin-right: 1rem;
}
.card-content { .card-content {
overflow-y: auto; overflow-y: auto;
max-height: 25rem; max-height: 25rem;
@ -50,13 +57,16 @@
border-bottom: 1px solid whitesmoke; border-bottom: 1px solid whitesmoke;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: flex-end;
justify-content: space-between; justify-content: space-between;
box-sizing: border-box; box-sizing: border-box;
cursor: move;
background: white; background: white;
padding-bottom: 3px; padding-bottom: 3px;
} }
.item-title {
display: inline-block;
width: 100%;
}
.card-item:last-child { .card-item:last-child {
border: none; border: none;

View File

@ -54,13 +54,13 @@ export class SavedPageCardComponent extends SubscriberBase implements OnInit {
format(item: DataReference) { format(item: DataReference) {
if (item.type === CardType.Note) { if (item.type === CardType.Note) {
return `Note: ${(getFromCardCache(item, this.cache).data as NoteItem).title}`; return `${(getFromCardCache(item, this.cache).data as NoteItem).title}`;
} else if (item.type === CardType.Passage) { } else if (item.type === CardType.Passage) {
return `Passage: ${item.qry}`; return `${item.qry}`;
} else if (item.type === CardType.Strongs) { } else if (item.type === CardType.Strongs) {
return `Strongs: ${item.qry}`; return `${item.qry}`;
} else if (item.type === CardType.Word) { } else if (item.type === CardType.Word) {
return `Word Search: ${item.qry}`; return `${item.qry}`;
} }
return ''; return '';
} }

View File

@ -15,6 +15,5 @@ mat-card {
padding: 0 1rem 0 1rem; padding: 0 1rem 0 1rem;
overflow-y: scroll; overflow-y: scroll;
height: calc(100vh - 66px); height: calc(100vh - 66px);
width: calc(100% - 15px);
margin-top: 2px; margin-top: 2px;
} }

View File

@ -15,6 +15,5 @@ mat-card {
padding: 0 1rem 0 1rem; padding: 0 1rem 0 1rem;
overflow-y: scroll; overflow-y: scroll;
height: calc(100vh - 66px); height: calc(100vh - 66px);
width: calc(100% - 15px);
margin-top: 2px; margin-top: 2px;
} }

View File

@ -28,6 +28,7 @@ export class Swipe {
y2: 0, y2: 0,
scrolling: null, scrolling: null,
manual: false, manual: false,
side: null,
}; };
constructor(private leftDrawer: MatSidenav, private rightDrawer: MatSidenav, private cd: ChangeDetectorRef) {} constructor(private leftDrawer: MatSidenav, private rightDrawer: MatSidenav, private cd: ChangeDetectorRef) {}
@ -58,12 +59,13 @@ export class Swipe {
this.swipeInfo.y2 = 0; this.swipeInfo.y2 = 0;
this.swipeInfo.scrolling = null; this.swipeInfo.scrolling = null;
this.swipeInfo.manual = false; this.swipeInfo.manual = false;
this.swipeInfo.side = null;
} }
/** /**
* Handles touch move events to detect if the user is attempting to scroll or swipe. * Handles touch move events to detect if the user is attempting to scroll or swipe.
* If the user moves the touch more than 5 px vertically then we assume the user is scrolling. * If the user moves the touch more than 5 px vertically then we assume the user is scrolling.
* If the user moves the touch more than 5 px horizontally then we assume the user is swiping and disable scrolling. * If the user moves the touch more than 10 px horizontally then we assume the user is swiping and disable scrolling.
* Touch end cleans up the scroll disabling. * Touch end cleans up the scroll disabling.
*/ */
private bodyTouchMove(event: TouchEvent) { private bodyTouchMove(event: TouchEvent) {
@ -75,6 +77,17 @@ export class Swipe {
let offset = this.swipeInfo.x2 - this.swipeInfo.x1; let offset = this.swipeInfo.x2 - this.swipeInfo.x1;
const side = this.determineSide(offset); const side = this.determineSide(offset);
// if the user swipes one direction then the other without removing the touch,
// we should ignore it... i think...
if (
this.swipeInfo.side !== null &&
this.swipeInfo.side.direction !== null &&
this.swipeInfo.side.direction !== side.direction
) {
return;
}
this.swipeInfo.side = side;
// the user is swiping // the user is swiping
// ignore swiping if the menu is not over // ignore swiping if the menu is not over
if (side.drawer.mode !== 'over') { if (side.drawer.mode !== 'over') {
@ -85,14 +98,14 @@ export class Swipe {
let translate = 0; let translate = 0;
if (side.drawer.opened) { if (side.drawer.opened) {
// if nav is open then offset should be negative // if nav is open then offset should be negative
if (this.isOpening(offset, side.drawer)) { if (this.isOpening(offset)) {
return; return;
} }
translate = offset; translate = offset;
} else { } else {
// if nav is closed then offset should be positive // if nav is closed then offset should be positive
if (!this.isOpening(offset, side.drawer)) { if (!this.isOpening(offset)) {
return; return;
} }
// make sure the offset is not greater than sidenav width // make sure the offset is not greater than sidenav width
@ -129,43 +142,52 @@ export class Swipe {
this.swipeInfo.y2 = t.pageY; this.swipeInfo.y2 = t.pageY;
const offset = this.swipeInfo.x2 - this.swipeInfo.x1; const offset = this.swipeInfo.x2 - this.swipeInfo.x1;
const side = this.determineSide(offset);
// decide if we need to hide or show the sidenav // decide if we need to hide or show the sidenav
if (this.swipeInfo.scrolling === false) { if (this.swipeInfo.scrolling === false) {
// enable scrolling again // enable scrolling again
window.document.body.classList.remove('lock-scroll'); window.document.body.classList.remove('lock-scroll');
// restore backdrop transition // restore backdrop transition
this.backdropEl.style.transitionDuration = null; this.backdropEl.style.transitionDuration = null;
// if the menu is not over then ignore // if the menu is not over then ignore
if (side.drawer.mode !== 'over') { if (this.swipeInfo.side.drawer.mode !== 'over') {
return; return;
} }
// if the offset is < 0 and the sidenav is not open then ignore it // if you're swiping open and the drawer is already open.
// if the offset is > 0 and the sideNav is open then ignore it if (this.isOpening(offset) && this.swipeInfo.side.drawer.opened) {
if ( console.log('ignoring end event (already open)');
(!this.isOpening(offset, side.drawer) && !side.drawer.opened) ||
(this.isOpening(offset, side.drawer) && side.drawer.opened)
) {
return; return;
} }
// is the offset < 50% of width then ignore and reset position // if you're swiping closed and the drawer is not open
if (Math.abs(this.swipeInfo.x2 - this.swipeInfo.x1) < side.drawer._width * 0.5) { if (!this.isOpening(offset) && !this.swipeInfo.side.drawer.opened) {
console.log('resetting to closed (already closed)');
this.swipeInfo.side.el.style.transform = null;
this.swipeInfo.side.el.style.boxShadow = 'none';
this.backdropEl.style.visibility = null; this.backdropEl.style.visibility = null;
if (side.drawer.opened) { this.backdropEl.style.backgroundColor = null;
// reset drawer position return;
side.el.style.transform = 'none'; }
// reset background opacity
// if the change is less than the min, just ignore it.
// this block puts everything back the way it was.
console.log(`Offset: ${Math.abs(offset)}, Tolerance: ${this.swipeInfo.side.drawer._width * 0.08}`);
if (Math.abs(offset) < this.swipeInfo.side.drawer._width * 0.08) {
this.backdropEl.style.visibility = null;
if (this.swipeInfo.side.drawer.opened) {
// reset to open position
console.log('resetting to open (no tolerance)');
this.swipeInfo.side.el.style.transform = 'none';
this.backdropEl.style.backgroundColor = 'rgba(0,0,0,0.6)'; this.backdropEl.style.backgroundColor = 'rgba(0,0,0,0.6)';
} else { } else {
// reset drawer position // reset to closed position
side.el.style.transform = null; console.log('resetting to closed (no tolerance)');
// reset background opacity this.swipeInfo.side.el.style.transform = null;
this.swipeInfo.side.el.style.boxShadow = 'none';
this.backdropEl.style.backgroundColor = null; this.backdropEl.style.backgroundColor = null;
side.el.style.boxShadow = 'none';
} }
return; return;
} }
@ -177,21 +199,23 @@ export class Swipe {
this.disableAnimation$.next(true); this.disableAnimation$.next(true);
this.cd.markForCheck(); this.cd.markForCheck();
// wait for the end of the transition so we can reset anything we hacked to make this work // wait for the end of the transition so we can reset anything we hacked to make this work
side.el.addEventListener('transitionend', this.transitionEndHandler); this.swipeInfo.side.el.addEventListener('transitionend', this.transitionEndHandler);
// wait one frame for the handler to be established before setting the transition // wait one frame for the handler to be established before setting the transition
requestAnimationFrame(() => { requestAnimationFrame(() => {
side.el.style.transition = '400ms cubic-bezier(0.25, 0.8, 0.25, 1)'; this.swipeInfo.side.el.style.transition = '400ms cubic-bezier(0.25, 0.8, 0.25, 1)';
this.cd.markForCheck(); this.cd.markForCheck();
if (side.drawer.opened) { if (this.swipeInfo.side.drawer.opened) {
console.log('manually transitioning (closed)');
// update translate3d of sidenav so that it animates closed // update translate3d of sidenav so that it animates closed
if (side.direction === 'left') { if (this.swipeInfo.side.direction === 'left') {
side.el.style.transform = `translate3d(-100%, 0, 0)`; this.swipeInfo.side.el.style.transform = 'translate3d(-100%, 0, 0)';
} else { } else {
side.el.style.transform = `translate3d(100%, 0, 0)`; this.swipeInfo.side.el.style.transform = 'translate3d(100%, 0, 0)';
} }
} else { } else {
console.log('manually transitioning (open)');
// update the transform on the sidenav so that it animates open // update the transform on the sidenav so that it animates open
side.el.style.transform = `none`; this.swipeInfo.side.el.style.transform = 'none';
// reset background opacity // reset background opacity
this.backdropEl.style.backgroundColor = 'rgba(0,0,0,0.6)'; this.backdropEl.style.backgroundColor = 'rgba(0,0,0,0.6)';
} }
@ -200,32 +224,22 @@ export class Swipe {
} }
private resetDrawer() { private resetDrawer() {
const offset = this.swipeInfo.x2 - this.swipeInfo.x1; this.swipeInfo.side.el.removeEventListener('transitionend', this.transitionEndHandler);
const side = this.determineSide(offset); this.swipeInfo.side.el.style.transition = null;
side.el.removeEventListener('transitionend', this.transitionEndHandler);
this.backdropEl.style.visibility = null; this.backdropEl.style.visibility = null;
if (side.drawer.opened) { this.backdropEl.style.backgroundColor = null;
if (this.swipeInfo.side.drawer.opened) {
console.log('manually transitioning (final closed)');
// make the backdrop hide as if the sidenav is closed // make the backdrop hide as if the sidenav is closed
this.backdropEl.classList.remove('mat-drawer-shown'); this.backdropEl.classList.remove('mat-drawer-shown');
// reset the backgroundColor override we set so it will work normally in the future this.swipeInfo.side.el.style.transform = 'none';
this.backdropEl.style.backgroundColor = null; this.swipeInfo.side.drawer.toggle(false);
// reset the transition and transform properties so the sidenav doesn't get confused when it closes
side.el.style.transition = null;
side.el.style.transform = 'none';
// update the sidenav state to closed
side.drawer.toggle(false);
} else { } else {
console.log('manually transitioning (final open)');
// make the backdrop show as if the sidenav is open // make the backdrop show as if the sidenav is open
this.backdropEl.classList.add('mat-drawer-shown'); this.backdropEl.classList.add('mat-drawer-shown');
// reset the backgroundColor override we set so it will work normally in the future this.swipeInfo.side.drawer.toggle(true);
this.backdropEl.style.backgroundColor = null;
// reset the transition and transform properties so the sidenav doesn't get confused when it closes
side.el.style.transition = null;
side.drawer.toggle(true);
} }
this.cd.markForCheck(); this.cd.markForCheck();
@ -237,8 +251,8 @@ export class Swipe {
}); });
} }
private isOpening(offset: number, drawer: MatSidenav) { private isOpening(offset: number) {
if (drawer.position === 'end') { if (this.swipeInfo.side.direction === 'right') {
return offset < 0; // its on the right not the left, so its inverted. return offset < 0; // its on the right not the left, so its inverted.
} else { } else {
return offset > 0; return offset > 0;
@ -263,13 +277,14 @@ export class Swipe {
return true; return true;
} }
if (Math.abs(this.swipeInfo.x2 - this.swipeInfo.x1) > 5) { if (Math.abs(this.swipeInfo.x2 - this.swipeInfo.x1) > 10) {
// if the user has moved more than 5 pixels x then they're swiping // if the user has moved more than 5 pixels x then they're swiping
this.swipeInfo.scrolling = false; this.swipeInfo.scrolling = false;
// disable scrolling // disable scrolling
window.document.body.classList.add('lock-scroll'); window.document.body.classList.add('lock-scroll');
if (this.isIosDevice) { if (this.isIosDevice) {
// css overflow:hidden doesn't work on the body for iOS so we have to use a non-passive listener and preventdefault to prevent scrolling // css overflow:hidden doesn't work on the body for iOS so we have to use a
// non-passive listener and preventdefault to prevent scrolling
event.preventDefault(); event.preventDefault();
} }
} }
@ -278,7 +293,7 @@ export class Swipe {
return false; return false;
} }
private determineSide(offset: number) { private determineSide(offset: number): Side {
if (this.leftDrawer.opened) { if (this.leftDrawer.opened) {
return { drawer: this.leftDrawer, el: this.leftDrawerEl, direction: 'left' }; return { drawer: this.leftDrawer, el: this.leftDrawerEl, direction: 'left' };
} }
@ -298,6 +313,12 @@ export class Swipe {
} }
} }
interface Side {
drawer: MatSidenav;
el: HTMLElement;
direction: 'left' | 'right' | null;
}
export interface SwipeInfo { export interface SwipeInfo {
x1: number; x1: number;
y1: number; y1: number;
@ -305,6 +326,7 @@ export interface SwipeInfo {
y2: number; y2: number;
scrolling: boolean | null; scrolling: boolean | null;
manual: boolean; manual: boolean;
side: Side;
} }
@Injectable({ @Injectable({