Compare commits
2 commits
e1aa1342c2
...
412a542e03
| Author | SHA1 | Date | |
|---|---|---|---|
| 412a542e03 | |||
| 8509578c74 |
13 changed files with 455 additions and 19 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
|
||||
import { StandUp } from './standup';
|
||||
import { SupaService } from './supa.service';
|
||||
|
||||
|
|
@ -10,11 +10,17 @@ export class StandupService {
|
|||
// standupMap: Map<number, StandUp> = new Map();
|
||||
standupMap = {};
|
||||
standups: BehaviorSubject<any> = new BehaviorSubject([]);
|
||||
isListening: boolean = false;
|
||||
|
||||
constructor(
|
||||
private supa: SupaService,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Get StandUps from local store.
|
||||
* Requests data if store is emtpy.
|
||||
* @returns Observable<StandUp[]>
|
||||
*/
|
||||
getStandUps(): Observable<StandUp[]> {
|
||||
if (Object.values(this.standupMap).length === 0) {
|
||||
console.log('getStandUps - REFRESH')
|
||||
|
|
@ -25,31 +31,133 @@ export class StandupService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to realtime events from standup db.
|
||||
*/
|
||||
subscribeToStandups() {
|
||||
if (!this.isListening) {
|
||||
this.isListening = true;
|
||||
this.supa.client.from<StandUp>('standup').on('*', payload => {
|
||||
console.log('subscribeToStandups - REALTIME EVENT', payload);
|
||||
if ((payload.eventType === 'INSERT') || (payload.eventType === 'UPDATE')) {
|
||||
this.standupMap[payload.new.id] = payload.new;
|
||||
} else {
|
||||
delete this.standupMap[payload.old.id];
|
||||
}
|
||||
this.next();
|
||||
}).subscribe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests up to date data from API.
|
||||
* Returns the local copy.
|
||||
* @returns Observable<StandUp>
|
||||
*/
|
||||
refreshStandUps(): Observable<StandUp[]> {
|
||||
this.supa.client.from<StandUp>('standup').select('id, name, description')
|
||||
this.subscribeToStandups();
|
||||
this.supa.client.from<StandUp>('standup').select()
|
||||
.then(standups => this.updateStore(standups.body))
|
||||
.catch(error => console.log('Error: ', error));
|
||||
return this.standups.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the local store with provided standups
|
||||
* @param standups
|
||||
*/
|
||||
updateStore(standups: StandUp[]) {
|
||||
standups.forEach(e => {
|
||||
// this.standupMap.set(e.id, e);
|
||||
this.standupMap[e.id] = e;
|
||||
});
|
||||
this.standups.next(Object.values(this.standupMap));
|
||||
this.next();
|
||||
}
|
||||
|
||||
updateOne(standup: StandUp) {
|
||||
/**
|
||||
* Emits local store.
|
||||
*/
|
||||
next = () => this.standups.next(Object.values(this.standupMap));
|
||||
|
||||
/**
|
||||
* Retrieve standup from local store.
|
||||
* @param id
|
||||
*/
|
||||
getOne(id: number) {
|
||||
if (this.standupMap[id]) {
|
||||
return of(this.standupMap[id]);
|
||||
} else {
|
||||
const subject: Subject<StandUp> = new Subject();
|
||||
this.supa.client.from<StandUp>('standup').select('id, name, description')
|
||||
.filter(<never>'id', 'eq', id)
|
||||
.then(data => {
|
||||
this.updateStore([data.body[0]]);
|
||||
subject.next(data.body[0]);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
}
|
||||
|
||||
deleteOne(standup: StandUp) {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param standup
|
||||
*/
|
||||
updateOne(standup: StandUp): Observable<StandUp> {
|
||||
const subject: Subject<StandUp> = new Subject();
|
||||
this.supa.client.from<StandUp>('standup').update(standup)
|
||||
.match({ id: standup.id })
|
||||
.then(data => {
|
||||
subject.next(data.body[0]);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
|
||||
addOne(standup: StandUp) {
|
||||
|
||||
/**
|
||||
* Removes one standup from db.
|
||||
* @param standup
|
||||
*/
|
||||
deleteOne(standup: StandUp): Observable<StandUp> {
|
||||
const subject: Subject<StandUp> = new Subject();
|
||||
this.supa.client.from<StandUp>('standup').delete()
|
||||
.match({ id: standup.id })
|
||||
.then(data => {
|
||||
subject.next(standup);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a standup on the db.
|
||||
* @param standup
|
||||
*/
|
||||
addOne(standup: StandUp): Observable<StandUp> {
|
||||
const subject: Subject<StandUp> = new Subject();
|
||||
this.supa.client.from<StandUp>('standup').insert(standup)
|
||||
.then(data => {
|
||||
subject.next(data.body[0]);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,4 +2,9 @@ export class StandUp {
|
|||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
|
||||
constructor(name: string, description: string) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
16
src/app/api/supabase/story.service.spec.ts
Normal file
16
src/app/api/supabase/story.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { StoryService } from './story.service';
|
||||
|
||||
describe('StoryService', () => {
|
||||
let service: StoryService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(StoryService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
181
src/app/api/supabase/story.service.ts
Normal file
181
src/app/api/supabase/story.service.ts
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
|
||||
import { Story } from './story';
|
||||
import { SupaService } from './supa.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class StoryService {
|
||||
// storyMap: Map<number, Story> = new Map();
|
||||
storyMap = {};
|
||||
stories: BehaviorSubject<any> = new BehaviorSubject([]);
|
||||
subscribedStandUpIds: number[] = [];
|
||||
isListening: boolean = false;
|
||||
|
||||
constructor(
|
||||
private supa: SupaService,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Get Storys from local store.
|
||||
* Requests data if store is emtpy.
|
||||
* @param standup_id
|
||||
* @returns Observable<Story[]>
|
||||
*/
|
||||
getStories(standup_id: number): Observable<Story[]> {
|
||||
if (!this.subscribedStandUpIds.includes(standup_id)) {
|
||||
this.subscribeToStories(standup_id);
|
||||
console.log('getStories - REFRESH', standup_id)
|
||||
const subject: Subject<Story[]> = new Subject();
|
||||
this.supa.client.from<Story>('story').select()
|
||||
.filter(<never>'standup_id', 'eq', standup_id)
|
||||
.then(data => {
|
||||
this.updateStore(data.body);
|
||||
subject.next(data.body);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
} else {
|
||||
console.log('getStories - LOCAL', standup_id)
|
||||
const stories = Object.values<Story>(this.storyMap).filter(e => e.standup_id === standup_id)
|
||||
console.log('filteredStories', stories)
|
||||
return of(stories);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to realtime events from story db.
|
||||
*/
|
||||
subscribeToStories(standup_id: number) {
|
||||
// TODO check for this.subscribedStandUpIds.includes(standup_id)
|
||||
if (!this.isListening) {
|
||||
this.subscribedStandUpIds.push(standup_id);
|
||||
this.supa.client.from<Story>('story').on('*', payload => {
|
||||
console.log('subscribeToStories - REALTIME EVENT', payload)
|
||||
if ((payload.eventType === 'INSERT') || (payload.eventType === 'UPDATE')) {
|
||||
this.storyMap[payload.new.id] = payload.new;
|
||||
} else {
|
||||
delete this.storyMap[payload.old.id];
|
||||
}
|
||||
this.next();
|
||||
}).subscribe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests up to date data from API.
|
||||
* Returns the local copy.
|
||||
* @returns Observable<Story>
|
||||
*/
|
||||
// refreshStorys(): Observable<Story[]> {
|
||||
// this.subscribeToStories();
|
||||
// this.supa.client.from<Story>('story').select()
|
||||
// .then(stories => this.updateStore(stories.body))
|
||||
// .catch(error => console.log('Error: ', error));
|
||||
// return this.stories.asObservable();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Update the local store with provided stories
|
||||
* @param stories
|
||||
*/
|
||||
updateStore(stories: Story[]) {
|
||||
stories.forEach(e => {
|
||||
// this.storyMap.set(e.id, e);
|
||||
this.storyMap[e.id] = e;
|
||||
});
|
||||
this.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits local store.
|
||||
*/
|
||||
next = () => this.stories.next(Object.values(this.storyMap));
|
||||
|
||||
/**
|
||||
* Retrieve story from local store.
|
||||
* @param id
|
||||
*/
|
||||
getOne(id: number) {
|
||||
if (this.storyMap[id]) {
|
||||
return of(this.storyMap[id]);
|
||||
} else {
|
||||
const subject: Subject<Story> = new Subject();
|
||||
this.supa.client.from<Story>('story').select('id, name, description')
|
||||
.filter(<never>'id', 'eq', id)
|
||||
.then(data => {
|
||||
this.updateStore([data.body[0]]);
|
||||
subject.next(data.body[0]);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param story
|
||||
*/
|
||||
updateOne(story: Story): Observable<Story> {
|
||||
const subject: Subject<Story> = new Subject();
|
||||
this.supa.client.from<Story>('story').update(story)
|
||||
.match({ id: story.id })
|
||||
.then(data => {
|
||||
subject.next(data.body[0]);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes one story from db.
|
||||
* @param story
|
||||
*/
|
||||
deleteOne(story: Story): Observable<Story> {
|
||||
const subject: Subject<Story> = new Subject();
|
||||
this.supa.client.from<Story>('story').delete()
|
||||
.match({ id: story.id })
|
||||
.then(data => {
|
||||
subject.next(story);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a story on the db.
|
||||
* @param story
|
||||
*/
|
||||
addOne(story: Story): Observable<Story> {
|
||||
const subject: Subject<Story> = new Subject();
|
||||
this.supa.client.from<Story>('story').insert(story)
|
||||
.then(data => {
|
||||
subject.next(data.body[0]);
|
||||
subject.complete();
|
||||
})
|
||||
.catch(error => {
|
||||
subject.error(error);
|
||||
subject.complete();
|
||||
});
|
||||
return subject.asObservable();
|
||||
}
|
||||
|
||||
}
|
||||
13
src/app/api/supabase/story.ts
Normal file
13
src/app/api/supabase/story.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
export class Story {
|
||||
id: number;
|
||||
standup_id: number;
|
||||
user_id: string
|
||||
base64: string;
|
||||
created_at: string | Date;
|
||||
|
||||
constructor(user_id: string, standup_id: number, base64: string) {
|
||||
this.user_id = user_id;
|
||||
this.standup_id = standup_id;
|
||||
this.base64 = base64;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
</nav>
|
||||
<div class="container-fluid p-0">
|
||||
<div class="myContainer d-flex">
|
||||
<div class="menu">
|
||||
<div *ngIf="supa.user | async" class="menu">
|
||||
<app-channel-list></app-channel-list>
|
||||
</div>
|
||||
<div class="container content">
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { FormsModule } from '@angular/forms';
|
|||
|
||||
import { SupaService } from './api/supabase/supa.service';
|
||||
import { StandupService } from './api/supabase/standup.service';
|
||||
import { StoryService } from './api/supabase/story.service';
|
||||
import { AuthGuard } from './authguard.service';
|
||||
|
||||
import { AppComponent } from "./app.component";
|
||||
|
|
@ -40,6 +41,7 @@ import { DashboardComponent } from './dashboard/dashboard.component';
|
|||
providers: [
|
||||
SupaService,
|
||||
StandupService,
|
||||
StoryService,
|
||||
AuthGuard,
|
||||
],
|
||||
bootstrap: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<div class="list bg-dark text-white p-3">
|
||||
<p><strong>Standup</strong> <strong class="newBtn">+</strong></p>
|
||||
<p><strong>Standup</strong> <strong class="newBtn" (click)="createStandUp()">+</strong></p>
|
||||
<ul class="list-unstyled">
|
||||
<li *ngFor="let s of standups" [title]="s.description" [routerLink]="'/huddle/'+s.id">{{s.name}}</li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -26,4 +26,11 @@ export class ChannelListComponent implements OnInit {
|
|||
return this.standupSevice.getStandUps();
|
||||
}
|
||||
|
||||
createStandUp() {
|
||||
this.standupSevice.addOne(new StandUp('test', 'test')).subscribe(
|
||||
data => console.log(data),
|
||||
error => console.error(error)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
<div class="row">
|
||||
<div *ngIf="standup" class="row">
|
||||
<div class="col-12 col-sm-9">
|
||||
<legend #name contenteditable="true" (click)="dataUpdated=true">{{ standup.name }}</legend>
|
||||
<p #desc contenteditable="true" (click)="dataUpdated=true">{{ standup.description }}</p>
|
||||
</div>
|
||||
<div class="col-12 col-sm-3">
|
||||
<div class="float-right">
|
||||
<button class="btn btn-primary ml-1 mr-1" [disabled]="!dataUpdated" (click)="updateStandUp(name.innerText, desc.innerText)">Save</button>
|
||||
<button class="btn btn-danger ml-1 mr-1" (click)="deleteStandUp()">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<ah-recorder></ah-recorder>
|
||||
<ah-recorder (recordingEnded)="uploadStory($event)"></ah-recorder>
|
||||
</div>
|
||||
<div *ngFor="let user of users" class="col p-3">
|
||||
<div class="text-center" (click)="playStory(user)">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import { Component, OnInit, ViewChild } from "@angular/core";
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { SupabaseAuthUser } from '@supabase/supabase-js';
|
||||
import { StandUp } from '../api/supabase/standup';
|
||||
import { StandupService } from '../api/supabase/standup.service';
|
||||
import { Story } from '../api/supabase/story';
|
||||
import { StoryService } from '../api/supabase/story.service';
|
||||
import { SupaService } from '../api/supabase/supa.service';
|
||||
|
||||
@Component({
|
||||
|
|
@ -33,13 +39,34 @@ export class HuddleComponent implements OnInit {
|
|||
}
|
||||
];
|
||||
selectedUser;
|
||||
standup: StandUp;
|
||||
stories: Story[] = [];
|
||||
|
||||
constructor(
|
||||
private modalService: NgbModal,
|
||||
public supa: SupaService,
|
||||
private standupService: StandupService,
|
||||
private storyService: StoryService,
|
||||
private supaService: SupaService,
|
||||
private route: ActivatedRoute,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.params.subscribe(
|
||||
params => {
|
||||
if (params.id) {
|
||||
this.standupService.getOne(params.id).subscribe(
|
||||
data => {
|
||||
console.log(data);
|
||||
this.standup = data;
|
||||
this.loadStories(data.id).subscribe(stories => this.stories = stories);
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
playStory(user) {
|
||||
|
|
@ -91,4 +118,48 @@ export class HuddleComponent implements OnInit {
|
|||
}
|
||||
this.selectedUser = this.users[index + 1];
|
||||
}
|
||||
|
||||
updateStandUp(name:string, desc:string) {
|
||||
this.standup.name = name;
|
||||
this.standup.description = desc;
|
||||
this.standupService.updateOne(this.standup).subscribe(
|
||||
data => {
|
||||
console.log('Success', data);
|
||||
},
|
||||
error => {
|
||||
console.error('Failed', error);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
deleteStandUp() {
|
||||
this.standupService.deleteOne(this.standup).subscribe(
|
||||
data => {
|
||||
console.log('Success', data);
|
||||
},
|
||||
error => {
|
||||
console.error('Failed', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async uploadStory(base64: string) {
|
||||
console.log('uploadStory', event);
|
||||
const user: SupabaseAuthUser = await this.supaService.client.auth.user();
|
||||
// TODO ID muss in DB noch autoincremented werden.
|
||||
const story = new Story(user.id, this.standup.id, base64);
|
||||
this.storyService.addOne(story).subscribe(
|
||||
data => {
|
||||
console.log('Success', data);
|
||||
},
|
||||
error => {
|
||||
console.error('Failed', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loadStories(id: number) {
|
||||
return this.storyService.getStories(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,21 @@
|
|||
<button class="btn btn-primary" (click)="openModal()">Record</button>
|
||||
<button class="btn btn-primary" (click)="openModal()">
|
||||
<svg width="20" height="20" style="height: 20px; width: 20px; margin-top: -4px;" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z"
|
||||
fill="currentColor" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12ZM20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C16.4183 4 20 7.58172 20 12Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
Record
|
||||
</button>
|
||||
|
||||
|
||||
<ng-template #content let-modal>
|
||||
<div class="modal-header">
|
||||
<strong>Record a stoy</strong>
|
||||
<span class="float-right cursor-pointer" (click)="modal.dismiss('Cross click')">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="20" height="20" style="height: 20px; width: 20px; margin-top: -4px;" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M6.2253 4.81108C5.83477 4.42056 5.20161 4.42056 4.81108 4.81108C4.42056 5.20161 4.42056 5.83477 4.81108 6.2253L10.5858 12L4.81114 17.7747C4.42062 18.1652 4.42062 18.7984 4.81114 19.1889C5.20167 19.5794 5.83483 19.5794 6.22535 19.1889L12 13.4142L17.7747 19.1889C18.1652 19.5794 18.7984 19.5794 19.1889 19.1889C19.5794 18.7984 19.5794 18.1652 19.1889 17.7747L13.4142 12L19.189 6.2253C19.5795 5.83477 19.5795 5.20161 19.189 4.81108C18.7985 4.42056 18.1653 4.42056 17.7748 4.81108L12 10.5858L6.2253 4.81108Z"
|
||||
fill="currentColor" />
|
||||
|
|
@ -23,7 +33,7 @@
|
|||
d="M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12ZM20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4C16.4183 4 20 7.58172 20 12Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
Record
|
||||
Start recording
|
||||
</button>
|
||||
<button *ngIf="isRecording" class="btn btn-danger" (click)="stopRecording()">Stop</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
|
||||
import * as rrtc from 'recordrtc';
|
||||
|
||||
|
|
@ -10,6 +10,7 @@ import * as rrtc from 'recordrtc';
|
|||
export class RecorderComponent implements OnInit {
|
||||
@ViewChild("content") content;
|
||||
@ViewChild("activeStory") video;
|
||||
@Output('recordingEnded') recordingEnded: EventEmitter<string> = new EventEmitter();
|
||||
stream: MediaStream;
|
||||
recorder: rrtc.RecordRTCPromisesHandler;
|
||||
modal: NgbModalRef;
|
||||
|
|
@ -46,12 +47,24 @@ export class RecorderComponent implements OnInit {
|
|||
}
|
||||
|
||||
async stopRecording() {
|
||||
const that = this;
|
||||
this.isRecording = false;
|
||||
await this.recorder.stopRecording();
|
||||
let blob = await this.recorder.getBlob();
|
||||
// TODO upload instead
|
||||
rrtc.invokeSaveAsDialog(blob, 'Recorded-Video.webm');
|
||||
this.modal.close();
|
||||
// read as b64
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(blob);
|
||||
reader.onloadend = function() {
|
||||
const base64data:string = String(reader.result);
|
||||
console.log(base64data);
|
||||
that.recordingEnded.emit(base64data);
|
||||
that.modal.close();
|
||||
}
|
||||
const handleError = (error) => {
|
||||
console.error(error);
|
||||
}
|
||||
reader.onerror = handleError;
|
||||
reader.onabort = handleError;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue