Skip to content

Commit

Permalink
fix(grid): better fullscreen on iOS devices (#171)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickmichalina authored Jul 5, 2019
1 parent 553fbdc commit 145832c
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ng-container *ngTemplateOutlet="gridListOverlayTemplate"></ng-container>
</div>
<div class="fg mg-auto" style="display: flex; align-items: center;" [style.max-width.px]="baseMaxWidth">
<div [style.padding-top]="aspectRatioPercentage"></div>
<div [style.padding-top.%]="aspectRatioPercentage"></div>
<div #floGridListContainer class="fg mg-auto list-container" [style.max-width]="maxWidth" [style.top]="top">
<ng-container *ngFor="let item of viewItemChange | async; index as idx; trackBy: trackByFn">
<div #floGridListItemContainer
Expand All @@ -15,8 +15,8 @@
[floGridListDragDropItem]="item.value"
[floGridListDragDropIndex]="idx"
[floGridListDragDropGridRef]="this"
[style.flex-basis]="item.flexBasis"
[style.padding-top]="item.padTop"
[style.flex-basis.%]="item.flexBasis"
[style.padding-top.%]="item.padTop"
[attr.id]="item?.value?.id">
<ng-container [ngSwitch]="item.hasValue">
<div *ngSwitchCase="true" class="fg list-item-some">
Expand Down
136 changes: 83 additions & 53 deletions projects/flosportsinc/ng-grid-list/common/grid/grid.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { async, TestBed } from '@angular/core/testing'
import { async, TestBed, fakeAsync, tick, discardPeriodicTasks } from '@angular/core/testing'
import { FloGridListViewComponent } from './grid.component'
import { FloGridListModule } from '../ng-grid-list.module'
import { DEFAULT_FLO_GRID_LIST_DEFAULT_VIEWCOUNT, DEFAULT_FLO_GRID_LIST_ASPECT_RATIO } from '../ng-grid-list.module.defaults'
import { take } from 'rxjs/operators'
import { PLATFORM_ID, Component, NgModule, ChangeDetectorRef, Renderer2 } from '@angular/core'
import { PLATFORM_ID, Component, NgModule } from '@angular/core'
import { By } from '@angular/platform-browser'
import {
FLO_GRID_LIST_MIN_COUNT, FLO_GRID_LIST_MAX_COUNT, FLO_GRID_LIST_OVERLAY_ENABLED,
Expand Down Expand Up @@ -75,7 +75,10 @@ const setupCountSomeNoneTests = (count: number, items: any[] = []) => {
sut.hoistInstance.count = count
sut.hoistFixture.detectChanges()

return sut.instance.gridItemContainers.toArray()
return {
collection: sut.instance.gridItemContainers.toArray(),
sut
}
}

describe(FloGridListViewComponent.name, () => {
Expand Down Expand Up @@ -145,6 +148,18 @@ describe(FloGridListViewComponent.name, () => {
it('should expose setter function', () => testInputPropSetFunc('selectedId', 'setSelectedId', 'awesome-id'))
})

describe('fullscreen', () => {
it('no', () => {
const sut = createSut()
// tslint:disable-next-line: no-if-statement
if (window.outerHeight - window.innerHeight <= 1) {
expect(sut.instance.isFullscreen()).toEqual(true)
} else {
expect(sut.instance.isFullscreen()).toEqual(false)
}
})
})

describe('aspectRatio property', () => {
it('should double bind', () => testInputProperty('aspectRatio', 0.5625))
it('should expose setter function', () => testInputPropSetFunc('aspectRatio', 'setAspectRatio', 0.5625))
Expand All @@ -158,20 +173,6 @@ describe(FloGridListViewComponent.name, () => {
const sut = createSut().instance
expect(TestBed.get(FLO_GRID_LIST_ASPECT_RATIO)).toEqual(DEFAULT_FLO_GRID_LIST_ASPECT_RATIO)
})
it('should get native', () => {
const sut = createSut().instance
expect(sut.getNativeAspectRatio()).toEqual(window.screen.height / window.screen.width)
})

it('should get native when orientation is landscape', () => {
const sut = createSut().instance
const { width, height } = (<any>window).screen;
(<any>window).screen = { width: 300, height: 400 }
expect(window.screen.height).toEqual(400)
expect(window.screen.width).toEqual(300)
expect(sut.getNativeAspectRatio()).toEqual(window.screen.width / window.screen.height);
(<any>window).screen = { width, height } // reset window object
})

it('should run change detection on fullscreen change', () => {
const sut = createSut()
Expand Down Expand Up @@ -291,36 +292,42 @@ describe(FloGridListViewComponent.name, () => {
})

describe('when count equals 1', () => {
it('should show 1 empty', () => {
it('should show 1 empty', fakeAsync(() => {
const result = setupCountSomeNoneTests(1, [])
expect(result.length).toEqual(1)
expect(result[0].nativeElement.innerText).toEqual('EMPTY')
})
it('should show 1 filled', () => {
tick(0)
result.sut.hoistFixture.detectChanges()
expect(result.collection.length).toEqual(1)
expect(result.collection[0].nativeElement.innerText).toEqual('EMPTY')
discardPeriodicTasks()
}))
it('should show 1 filled', fakeAsync(() => {
const result = setupCountSomeNoneTests(1, [{ id: '1', value: 'SOME_VALUE' }])
expect(result.length).toEqual(1)
expect(result[0].nativeElement.innerText).toEqual('SOME_VALUE')
})
tick(0)
result.sut.hoistFixture.detectChanges()
expect(result.collection.length).toEqual(1)
expect(result.collection[0].nativeElement.innerText).toEqual('SOME_VALUE')
discardPeriodicTasks()
}))
})

describe('when count equals 2', () => {
it('should show 2 empty', () => {
const result = setupCountSomeNoneTests(2, [])
expect(result.length).toEqual(2)
expect(result[0].nativeElement.innerText).toEqual('EMPTY')
expect(result[1].nativeElement.innerText).toEqual('EMPTY')
expect(result.collection.length).toEqual(2)
expect(result.collection[0].nativeElement.innerText).toEqual('EMPTY')
expect(result.collection[1].nativeElement.innerText).toEqual('EMPTY')
})
it('should show 1 empty, 1 filled', () => {
const result = setupCountSomeNoneTests(2, [undefined, { id: '1', value: 'SOME_VALUE' }])
expect(result.length).toEqual(2)
expect(result[0].nativeElement.innerText).toEqual('EMPTY')
expect(result[1].nativeElement.innerText).toEqual('SOME_VALUE')
expect(result.collection.length).toEqual(2)
expect(result.collection[0].nativeElement.innerText).toEqual('EMPTY')
expect(result.collection[1].nativeElement.innerText).toEqual('SOME_VALUE')
})
it('should show 2 filled', () => {
const result = setupCountSomeNoneTests(2, [{ id: '1', value: 'SOME_VALUE_1' }, { id: '2', value: 'SOME_VALUE_2' }])
expect(result.length).toEqual(2)
expect(result[0].nativeElement.innerText).toEqual('SOME_VALUE_1')
expect(result[1].nativeElement.innerText).toEqual('SOME_VALUE_2')
expect(result.collection.length).toEqual(2)
expect(result.collection[0].nativeElement.innerText).toEqual('SOME_VALUE_1')
expect(result.collection[1].nativeElement.innerText).toEqual('SOME_VALUE_2')
})
})

Expand Down Expand Up @@ -482,37 +489,51 @@ describe(FloGridListViewComponent.name, () => {
})]
}).compileComponents()
})
it('should handle counts of 1', () => {
it('should handle counts of 1', fakeAsync(() => {
const sut = createSut()
sut.hoistInstance.items = [SAMPLE_ITEM_1]
sut.instance.setCount(1)
tick(0)
sut.hoistFixture.detectChanges()
expect(sut.instance.selectedIndex).toEqual(0)
})
it('should handle counts of 2', () => {
discardPeriodicTasks()
}))
it('should handle counts of 2', fakeAsync(() => {
const sut = createSut()
sut.hoistInstance.items = [SAMPLE_ITEM_1]
sut.instance.setCount(2)
tick(0)
sut.hoistFixture.detectChanges()
expect(sut.instance.selectedIndex).toEqual(1)
})
it('should handle counts of 3', () => {
discardPeriodicTasks()
}))
it('should handle counts of 3', fakeAsync(() => {
const sut = createSut()
sut.hoistInstance.items = [SAMPLE_ITEM_1]
sut.instance.setCount(3)
tick(0)
sut.hoistFixture.detectChanges()
expect(sut.instance.selectedIndex).toEqual(1)
})
it('should handle counts of 4', () => {
discardPeriodicTasks()
}))
it('should handle counts of 4', fakeAsync(() => {
const sut = createSut()
sut.hoistInstance.items = [SAMPLE_ITEM_1]
sut.instance.setCount(4)
tick(0)
sut.hoistFixture.detectChanges()
expect(sut.instance.selectedIndex).toEqual(1)
})

it('should handle multi items w/ counts', () => {
discardPeriodicTasks()
}))
it('should handle multi items w/ counts', fakeAsync(() => {
const sut = createSut()
sut.hoistInstance.items = [SAMPLE_ITEM_1, SAMPLE_ITEM_2]
sut.instance.setCount(4)
tick(0)
sut.hoistFixture.detectChanges()
expect(sut.instance.selectedIndex).toEqual(2)
})
discardPeriodicTasks()
}))
})
})

Expand Down Expand Up @@ -672,26 +693,32 @@ describe(FloGridListViewComponent.name, () => {
})

describe('findNextEmptyIndex', () => {
it('should return next index when in viewcount', () => {
it('should return next index when in viewcount', fakeAsync(() => {
const sut = createSut()
sut.instance.setCount(4)
sut.hoistInstance.items = [SAMPLE_ITEM_1]
tick(0)
expect(sut.instance.findNextEmptyIndex()).toEqual(1)
})
discardPeriodicTasks()
}))

it('should return -1 when no index is next', () => {
it('should return -1 when no index is next', fakeAsync(() => {
const sut = createSut()
sut.instance.setCount(1)
sut.hoistInstance.items = [SAMPLE_ITEM_1]
tick(0)
expect(sut.instance.findNextEmptyIndex()).toEqual(-1)
})
discardPeriodicTasks()
}))

it('should return -1 when out of bounds', () => {
it('should return -1 when out of bounds', fakeAsync(() => {
const sut = createSut()
sut.instance.setCount(2)
sut.hoistInstance.items = [SAMPLE_ITEM_1, SAMPLE_ITEM_2]
tick(0)
expect(sut.instance.findNextEmptyIndex()).toEqual(-1)
})
discardPeriodicTasks()
}))
})

describe('fillNextEmpty', () => {
Expand All @@ -703,13 +730,16 @@ describe(FloGridListViewComponent.name, () => {
expect(sut.hoistInstance.items[0]).toEqual(SAMPLE_ITEM_1)
})

it('should fill first empty', () => {
it('should fill first empty', fakeAsync(() => {
const sut = createSut()
sut.instance.setCount(4)
sut.hoistInstance.items = [SAMPLE_ITEM_1]
sut.instance.fillNextEmpty(SAMPLE_ITEM_2)
tick(0)
sut.hoistFixture.detectChanges()
expect(sut.hoistInstance.items[1]).toEqual(SAMPLE_ITEM_2)
})
discardPeriodicTasks()
}))
})

describe('isItemInAnotherIndex', () => {
Expand Down
52 changes: 22 additions & 30 deletions projects/flosportsinc/ng-grid-list/common/grid/grid.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { isPlatformServer, isPlatformBrowser } from '@angular/common'
import { maybe, IMaybe } from 'typescript-monads'
import { chunk, swapItemsViaIndices } from './helpers'
import { swapItemsViaIndices } from './helpers'
import { Subject, fromEvent, of, interval, merge, BehaviorSubject } from 'rxjs'
import { map, startWith, mapTo, share, switchMapTo, tap, distinctUntilChanged, takeUntil, shareReplay } from 'rxjs/operators'
import { FloGridListOverlayDirective, FloGridListItemNoneDirective, FloGridListItemSomeDirective } from './grid.directive'
Expand Down Expand Up @@ -36,8 +36,8 @@ import {
export interface IViewItem<T> {
readonly value?: T
readonly hasValue: boolean
readonly flexBasis: string
readonly padTop: string
readonly flexBasis: number
readonly padTop: number
readonly isShowingBorder: boolean
readonly isSelected: boolean
readonly isNotSelected: boolean
Expand Down Expand Up @@ -318,9 +318,6 @@ export class FloGridListViewComponent<TItem extends IFloGridListBaseItem> implem
}

public readonly isFullscreen = () => isPlatformBrowser(this._platformId) ? 1 >= window.outerHeight - window.innerHeight : false
public readonly getNativeAspectRatio = () => window.screen.height > window.screen.width
? window.screen.width / window.screen.height
: window.screen.height / window.screen.width

get baseMaxWidth() {
return this.maxheight / this.aspectRatio
Expand All @@ -331,15 +328,17 @@ export class FloGridListViewComponent<TItem extends IFloGridListBaseItem> implem
}

get aspectRatioPercentage() {
return `${(this.isFullscreen() ? this.getNativeAspectRatio() : this.aspectRatio) * 100 + '%'}`
return this.aspectRatio * 100
}

get top() {
return this.count === 2
? this.isIE11
return this.isIE11
? this.count === 2
? '25%'
: 'inherit'
: '0px'
: 0
: this.count === 2 || this.isFullscreen()
? 'inherit'
: 0
}

private readonly viewItemSource = new BehaviorSubject<ReadonlyArray<IViewItem<TItem>>>([])
Expand Down Expand Up @@ -408,32 +407,25 @@ export class FloGridListViewComponent<TItem extends IFloGridListBaseItem> implem
this._cdRef.markForCheck()
}

// TODO: optimize!
createViewItems = () => {
const square = Math.ceil(Math.sqrt(this.count))

const stub = new Array<IMaybe<TItem>>(this.count)
.fill(maybe())
.map((val, idx) => this.items[idx] ? maybe(this.items[idx]) : val)

return chunk(square, stub)
.reduce((acc, curr) => {
return [
...acc,
...curr.map((value, itemIndex, arrb) => {
const isSelected = this.selectedIndex === acc.length + itemIndex
return {
hasValue: value.isSome(),
value: value.valueOrUndefined(),
flexBasis: arrb.length > 1 ? 100 / arrb.length + '%' : 100 / square + '%',
padTop: arrb.length > 1 ? 56.25 / arrb.length + '%' : 56.25 / square + '%',
isShowingBorder: isSelected && this.count > 1,
isSelected,
isNotSelected: !isSelected
}
})
]
}, [] as ReadonlyArray<IViewItem<TItem>>)
return stub.map<IViewItem<TItem>>((value, idx) => {
const isSelected = this.selectedIndex === idx
return {
hasValue: value.isSome(),
value: value.valueOrUndefined(),
flexBasis: 100 / square,
padTop: this.aspectRatioPercentage / square,
isShowingBorder: isSelected && this.count > 1,
isSelected,
isNotSelected: !isSelected
}
})
}

update() {
Expand Down
19 changes: 1 addition & 18 deletions projects/flosportsinc/ng-grid-list/common/grid/helpers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { swapItemsViaIndices, chunk } from './helpers'
import { swapItemsViaIndices } from './helpers'

const COLLECTION_1: ReadonlyArray<any> = [{ prop: 1 }, { prop: 2 }, { prop: 3 }]

Expand Down Expand Up @@ -27,20 +27,3 @@ describe(swapItemsViaIndices.name, () => {
expect(sut[2]).toBeUndefined()
})
})

describe('chunk utility function', () => {
it('should work', () => {
const sut = chunk(1, [{}, {}, {}, {}])
expect(sut.length).toEqual(4)
})

it('should handle empty collection', () => {
const sut = chunk(2, [{}, {}, {}])
expect(sut.length).toEqual(2)
})

it('should handle empty collection', () => {
const sut = chunk(1)
expect(sut.length).toEqual(0)
})
})
6 changes: 0 additions & 6 deletions projects/flosportsinc/ng-grid-list/common/grid/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,3 @@ export const swapItemsViaIndices =

return _cloned
}

export const chunk = <T>(size: number, collection: ReadonlyArray<T> = []) =>
collection.reduce((acc, _, index) =>
index % size === 0
? [...acc, collection.slice(index, index + size)]
: acc, [])
Loading

0 comments on commit 145832c

Please sign in to comment.