Mercurial > hg > ugly-duckling
changeset 464:50f61d1945db
Hook up some buttons for navigating history (undo / redo). Some refactoring to allow for the audio player to get updated as a consequence of a state change (the audio related to the current top of the stack is used).
author | Lucas Thompson <dev@lucas.im> |
---|---|
date | Fri, 30 Jun 2017 14:01:22 +0100 |
parents | c9c6b01e9b4f |
children | caef9a302bec |
files | src/app/app.component.html src/app/app.component.ts src/app/notebook-feed/notebook-feed.component.ts |
diffstat | 3 files changed, 64 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/src/app/app.component.html Fri Jun 30 13:59:51 2017 +0100 +++ b/src/app/app.component.html Fri Jun 30 14:01:22 2017 +0100 @@ -17,10 +17,15 @@ <ugly-audio-file-open (fileOpened)="onFileOpened($event); tray.close()" ></ugly-audio-file-open> - <!-- menu opens when trigger button is clicked --> <button md-icon-button (click)="tray.toggle()"> <md-icon>extension</md-icon> </button> + <button md-icon-button (click)="analyses.stepBack()"> + <md-icon>undo</md-icon> + </button> + <button md-icon-button (click)="analyses.stepForward()"> + <md-icon>redo</md-icon> + </button> </md-toolbar> </div> @@ -35,7 +40,6 @@ <ugly-notebook-feed (removeItem)="removeItem($event)" [analyses]="analyses.toIterable()" - [rootAudioUri]="rootAudioItem.uri" [onSeek]="onSeek"></ugly-notebook-feed> </div> </div>
--- a/src/app/app.component.ts Fri Jun 30 13:59:51 2017 +0100 +++ b/src/app/app.component.ts Fri Jun 30 14:01:22 2017 +0100 @@ -19,7 +19,7 @@ isLoadedRootAudioItem, Item, RootAudioItem, - LoadedRootAudioItem + getRootAudioItem } from './analysis-item/AnalysisItem'; import {OnSeekHandler} from './playhead/PlayHeadHelpers'; import {UrlResourceLifetimeManager} from './app.module'; @@ -38,7 +38,6 @@ private analyses: PersistentStack<Item>; // TODO some immutable state container describing entire session private nRecordings: number; // TODO user control for naming a recording private countingId: number; // TODO improve uniquely identifying items - private rootAudioItem: LoadedRootAudioItem; private onSeek: OnSeekHandler; constructor(private audioService: AudioPlayerService, @@ -53,7 +52,6 @@ this.nRecordings = 0; this.countingId = 0; this.onSeek = (time) => this.audioService.seekTo(time); - this.rootAudioItem = {} as any; // TODO eugh iconRegistry.addSvgIcon( 'duck', @@ -67,11 +65,12 @@ this.analyses.shift(); this.canExtract = false; } else { - this.rootAudioItem.audioData = (resource as AudioResource).samples; - if (this.rootAudioItem.audioData) { + const audioData = (resource as AudioResource).samples; + if (audioData) { + const rootAudio = getRootAudioItem(this.analyses.get(0)); this.canExtract = true; const currentRootIndex = this.analyses.findIndex(val => { - return isLoadedRootAudioItem(val) && val.uri === this.rootAudioItem.uri; + return isPendingRootAudioItem(val) && val.uri === rootAudio.uri; }); if (currentRootIndex !== -1) { this.analyses.set( @@ -79,7 +78,7 @@ Object.assign( {}, this.analyses.get(currentRootIndex), - {audioData: this.rootAudioItem.audioData} + {audioData} ) ); } @@ -130,7 +129,6 @@ mimeType: file.type, isExportable: createExportableItem } as RootAudioItem; - this.rootAudioItem = pending as LoadedRootAudioItem; // TODO this is silly // TODO re-ordering of items for display // , one alternative is a Angular Pipe / Filter for use in the Template @@ -144,19 +142,24 @@ this.canExtract = false; - const placeholderCard: AnalysisItem = { - parent: this.rootAudioItem, - hasSharedTimeline: true, - extractorKey: outputInfo.extractorKey, - outputId: outputInfo.outputId, - title: outputInfo.name, - description: outputInfo.outputId, - id: `${++this.countingId}`, - progress: 0 - }; - this.analyses.unshift(placeholderCard); - this.sendExtractionRequest(placeholderCard); - return placeholderCard.id; + const rootAudio = getRootAudioItem(this.analyses.get(0)); + + if (isLoadedRootAudioItem(rootAudio)) { + const placeholderCard: AnalysisItem = { + parent: rootAudio, + hasSharedTimeline: true, + extractorKey: outputInfo.extractorKey, + outputId: outputInfo.outputId, + title: outputInfo.name, + description: outputInfo.outputId, + id: `${++this.countingId}`, + progress: 0 + }; + this.analyses.unshift(placeholderCard); + this.sendExtractionRequest(placeholderCard); + return placeholderCard.id; + } + throw new Error('Cannot extract. No audio loaded'); } removeItem(item: Item): void { @@ -170,30 +173,6 @@ return toRemove; }, []); this.analyses.remove(...indicesToRemove); - if (isPendingRootAudioItem(item)) { - if (this.rootAudioItem.uri === item.uri) { - this.audioService.unload(); - const topItem = this.analyses.get(0); - const nullRootAudio: LoadedRootAudioItem = {uri: ''} as any; // TODO eugh - - if (topItem) { - if (isPendingAnalysisItem(topItem)) { - this.rootAudioItem = topItem.parent as LoadedRootAudioItem; - } else if (isPendingRootAudioItem(topItem)) { - this.rootAudioItem = topItem as LoadedRootAudioItem; - } else { - this.rootAudioItem = nullRootAudio; - } - } else { - this.rootAudioItem = nullRootAudio; - } - if (this.rootAudioItem) { - this.audioService.loadAudioFromUri(this.rootAudioItem.uri); - } - } else { - this.resourceManager.revokeUrlToResource(item.uri); - } - } } ngOnDestroy(): void {
--- a/src/app/notebook-feed/notebook-feed.component.ts Fri Jun 30 13:59:51 2017 +0100 +++ b/src/app/notebook-feed/notebook-feed.component.ts Fri Jun 30 14:01:22 2017 +0100 @@ -19,6 +19,7 @@ import {Dimension} from '../app.module'; import {Subscription} from 'rxjs/Subscription'; import {OnSeekHandler} from '../playhead/PlayHeadHelpers'; +import {AudioPlayerService} from '../services/audio-player/audio-player.service'; @Component({ selector: 'ugly-notebook-feed', @@ -27,25 +28,38 @@ changeDetection: ChangeDetectionStrategy.OnPush }) export class NotebookFeedComponent implements OnDestroy { - @Input() analyses: Item[]; - @Input() set rootAudioUri(uri: string) { - this._rootAudioUri = uri; + @Input() set analyses(analyses: Item[]) { + const front = analyses[0]; + if (analyses !== this.mAnalyses) { + if (front && getRootUri(front) !== this.currentAudioUri) { + this.audioService.unload(); + this.audioService.loadAudioFromUri(getRootUri(front)); + } + } + this.mAnalyses = analyses; + if (front) { + this.currentAudioUri = this.getCurrentAudioUri(); + } } + + get analyses(): Item[] { + return this.mAnalyses; + } + @Input() onSeek: OnSeekHandler; @Output() removeItem: EventEmitter<Item>; - get rootAudioUri(): string { - return this._rootAudioUri; - } - private _rootAudioUri: string; private resizeSubscription: Subscription; private width: number; private lastWidth: number; private timelines: Map<string, Timeline>; + private mAnalyses: Item[]; + private currentAudioUri: string; constructor( private ref: ChangeDetectorRef, - @Inject('DimensionObservable') private onResize: Observable<Dimension> + @Inject('DimensionObservable') private onResize: Observable<Dimension>, + private audioService: AudioPlayerService ) { this.removeItem = new EventEmitter<Item>(); this.timelines = new Map(); @@ -86,7 +100,7 @@ } isActiveItem(item: Item): boolean { - return this.rootAudioUri === getRootUri(item); + return this.getCurrentAudioUri() === getRootUri(item); } getOnSeekForItem(item: Item): (timeSeconds: number) => any { @@ -98,4 +112,15 @@ this.resizeSubscription.unsubscribe(); } } + + private getCurrentAudioUri(): string { + if (this.analyses.length === 0) { + return ''; + } + try { + return getRootUri(this.analyses[0]); + } catch (e) { + return ''; + } + } }