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",
"forceCodeForRefreshToken" : true
}
},
"cordova": {}
}

View File

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

View File

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

View File

@ -54,13 +54,13 @@ export class SavedPageCardComponent extends SubscriberBase implements OnInit {
format(item: DataReference) {
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) {
return `Passage: ${item.qry}`;
return `${item.qry}`;
} else if (item.type === CardType.Strongs) {
return `Strongs: ${item.qry}`;
return `${item.qry}`;
} else if (item.type === CardType.Word) {
return `Word Search: ${item.qry}`;
return `${item.qry}`;
}
return '';
}

View File

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

View File

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

View File

@ -28,6 +28,7 @@ export class Swipe {
y2: 0,
scrolling: null,
manual: false,
side: null,
};
constructor(private leftDrawer: MatSidenav, private rightDrawer: MatSidenav, private cd: ChangeDetectorRef) {}
@ -58,12 +59,13 @@ export class Swipe {
this.swipeInfo.y2 = 0;
this.swipeInfo.scrolling = null;
this.swipeInfo.manual = false;
this.swipeInfo.side = null;
}
/**
* 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 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.
*/
private bodyTouchMove(event: TouchEvent) {
@ -75,6 +77,17 @@ export class Swipe {
let offset = this.swipeInfo.x2 - this.swipeInfo.x1;
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
// ignore swiping if the menu is not over
if (side.drawer.mode !== 'over') {
@ -85,14 +98,14 @@ export class Swipe {
let translate = 0;
if (side.drawer.opened) {
// if nav is open then offset should be negative
if (this.isOpening(offset, side.drawer)) {
if (this.isOpening(offset)) {
return;
}
translate = offset;
} else {
// if nav is closed then offset should be positive
if (!this.isOpening(offset, side.drawer)) {
if (!this.isOpening(offset)) {
return;
}
// make sure the offset is not greater than sidenav width
@ -129,43 +142,52 @@ export class Swipe {
this.swipeInfo.y2 = t.pageY;
const offset = this.swipeInfo.x2 - this.swipeInfo.x1;
const side = this.determineSide(offset);
// decide if we need to hide or show the sidenav
if (this.swipeInfo.scrolling === false) {
// enable scrolling again
window.document.body.classList.remove('lock-scroll');
// restore backdrop transition
this.backdropEl.style.transitionDuration = null;
// if the menu is not over then ignore
if (side.drawer.mode !== 'over') {
if (this.swipeInfo.side.drawer.mode !== 'over') {
return;
}
// if the offset is < 0 and the sidenav is not open then ignore it
// if the offset is > 0 and the sideNav is open then ignore it
if (
(!this.isOpening(offset, side.drawer) && !side.drawer.opened) ||
(this.isOpening(offset, side.drawer) && side.drawer.opened)
) {
// if you're swiping open and the drawer is already open.
if (this.isOpening(offset) && this.swipeInfo.side.drawer.opened) {
console.log('ignoring end event (already open)');
return;
}
// is the offset < 50% of width then ignore and reset position
if (Math.abs(this.swipeInfo.x2 - this.swipeInfo.x1) < side.drawer._width * 0.5) {
// if you're swiping closed and the drawer is not open
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;
if (side.drawer.opened) {
// reset drawer position
side.el.style.transform = 'none';
// reset background opacity
this.backdropEl.style.backgroundColor = null;
return;
}
// 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)';
} else {
// reset drawer position
side.el.style.transform = null;
// reset background opacity
// reset to closed position
console.log('resetting to closed (no tolerance)');
this.swipeInfo.side.el.style.transform = null;
this.swipeInfo.side.el.style.boxShadow = 'none';
this.backdropEl.style.backgroundColor = null;
side.el.style.boxShadow = 'none';
}
return;
}
@ -177,21 +199,23 @@ export class Swipe {
this.disableAnimation$.next(true);
this.cd.markForCheck();
// 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
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();
if (side.drawer.opened) {
if (this.swipeInfo.side.drawer.opened) {
console.log('manually transitioning (closed)');
// update translate3d of sidenav so that it animates closed
if (side.direction === 'left') {
side.el.style.transform = `translate3d(-100%, 0, 0)`;
if (this.swipeInfo.side.direction === 'left') {
this.swipeInfo.side.el.style.transform = 'translate3d(-100%, 0, 0)';
} else {
side.el.style.transform = `translate3d(100%, 0, 0)`;
this.swipeInfo.side.el.style.transform = 'translate3d(100%, 0, 0)';
}
} else {
console.log('manually transitioning (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
this.backdropEl.style.backgroundColor = 'rgba(0,0,0,0.6)';
}
@ -200,32 +224,22 @@ export class Swipe {
}
private resetDrawer() {
const offset = this.swipeInfo.x2 - this.swipeInfo.x1;
const side = this.determineSide(offset);
side.el.removeEventListener('transitionend', this.transitionEndHandler);
this.swipeInfo.side.el.removeEventListener('transitionend', this.transitionEndHandler);
this.swipeInfo.side.el.style.transition = 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
this.backdropEl.classList.remove('mat-drawer-shown');
// reset the backgroundColor override we set so it will work normally in the future
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.el.style.transform = 'none';
// update the sidenav state to closed
side.drawer.toggle(false);
this.swipeInfo.side.el.style.transform = 'none';
this.swipeInfo.side.drawer.toggle(false);
} else {
console.log('manually transitioning (final open)');
// make the backdrop show as if the sidenav is open
this.backdropEl.classList.add('mat-drawer-shown');
// reset the backgroundColor override we set so it will work normally in the future
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.swipeInfo.side.drawer.toggle(true);
}
this.cd.markForCheck();
@ -237,8 +251,8 @@ export class Swipe {
});
}
private isOpening(offset: number, drawer: MatSidenav) {
if (drawer.position === 'end') {
private isOpening(offset: number) {
if (this.swipeInfo.side.direction === 'right') {
return offset < 0; // its on the right not the left, so its inverted.
} else {
return offset > 0;
@ -263,13 +277,14 @@ export class Swipe {
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
this.swipeInfo.scrolling = false;
// disable scrolling
window.document.body.classList.add('lock-scroll');
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();
}
}
@ -278,7 +293,7 @@ export class Swipe {
return false;
}
private determineSide(offset: number) {
private determineSide(offset: number): Side {
if (this.leftDrawer.opened) {
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 {
x1: number;
y1: number;
@ -305,6 +326,7 @@ export interface SwipeInfo {
y2: number;
scrolling: boolean | null;
manual: boolean;
side: Side;
}
@Injectable({