mirror of
https://github.com/fergalmoran/podnoms.git
synced 2025-12-22 09:18:08 +00:00
SignalR auth working
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
"@angular/platform-browser": "6.0.0",
|
||||
"@angular/platform-browser-dynamic": "6.0.0",
|
||||
"@angular/router": "6.0.0",
|
||||
"@aspnet/signalr": "^1.0.0-rtm-30751",
|
||||
"@ngrx/effects": "^5.1.0",
|
||||
"@ngrx/store": "^5.1.0",
|
||||
"@ngrx/store-devtools": "^5.1.0",
|
||||
|
||||
@@ -23,12 +23,29 @@ export const ADD_SUCCESS = '[Chat] Add Chat Success';
|
||||
export const ADD_FAIL = '[Chat] Add Chat Fail';
|
||||
export class AddAction implements Action {
|
||||
readonly type = ADD;
|
||||
constructor(public payload: ChatModel) {
|
||||
}
|
||||
constructor(public payload: ChatModel) {}
|
||||
}
|
||||
export class AddSuccessAction implements Action {
|
||||
readonly type = ADD_SUCCESS;
|
||||
constructor(public payload: ChatModel) {}
|
||||
}
|
||||
//#endregion
|
||||
//#region Add
|
||||
// the receive action is for messages from signalR
|
||||
// we don't want to initiate a POST to the server.
|
||||
export const RECEIVE = '[Chat] Receive Chat';
|
||||
export const RECEIVE_SUCCESS = '[Chat] Receive Chat Success';
|
||||
export const RECEIVE_FAIL = '[Chat] Receive Chat Fail';
|
||||
export class ReceiveAction implements Action {
|
||||
readonly type = RECEIVE;
|
||||
constructor(public payload: ChatModel) {
|
||||
console.log('chat.actions', 'RECEIVE', payload);
|
||||
}
|
||||
}
|
||||
export class ReceiveSuccessAction implements Action {
|
||||
readonly type = RECEIVE_SUCCESS;
|
||||
constructor(public payload: ChatModel) {
|
||||
console.log('chat.actions', 'RECEIVE_SUCESS', payload);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
@@ -37,5 +54,6 @@ export type Actions =
|
||||
| LoadSuccessAction
|
||||
| LoadFailAction
|
||||
| AddAction
|
||||
| AddSuccessAction;
|
||||
|
||||
| AddSuccessAction
|
||||
| ReceiveAction
|
||||
| ReceiveSuccessAction;
|
||||
|
||||
@@ -58,13 +58,11 @@ export class AppComponent implements OnInit {
|
||||
const chatterChannel = `${p.id}`;
|
||||
this._signalrService
|
||||
.init('userupdates')
|
||||
.then((r) => {
|
||||
this._signalrService.connection.on(
|
||||
chatterChannel,
|
||||
(result) => {
|
||||
this._toastyService.info(result);
|
||||
}
|
||||
);
|
||||
.then((listener) => {
|
||||
listener.on<string>(chatterChannel)
|
||||
.subscribe(result => {
|
||||
this._toastyService.info(result);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(
|
||||
|
||||
@@ -156,7 +156,7 @@ export function provideConfig() {
|
||||
authDomain: 'podnoms-api.firebaseapp.com',
|
||||
databaseURL: 'https://podnoms-api.firebaseio.com',
|
||||
projectId: 'podnoms-api',
|
||||
storageBucket: '',
|
||||
storageBucket: 'podnoms-api.appspot.com',
|
||||
messagingSenderId: '357461672895'
|
||||
}),
|
||||
AngularFireDatabaseModule,
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chat-controls" *ngIf="!loading">
|
||||
<input class="message-input" placeholder="Type your message here..." type="text" #message (keyup.enter)="sendMessage(message)">
|
||||
<div class="chat-controls">
|
||||
<input #message class="message-input" placeholder="Type your message and press enter..." type="text"
|
||||
(keyup.enter)="sendMessage(message)">
|
||||
<div class="chat-extra">
|
||||
<a href="#">
|
||||
<span class="extra-tooltip">Attach Document</span>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, ViewChild, ElementRef } from '@angular/core';
|
||||
import { ProfileService } from '../../services/profile.service';
|
||||
import { SignalRService } from '../../services/signalr.service';
|
||||
import { ProfileModel } from 'app/models/profile.model';
|
||||
@@ -15,11 +15,17 @@ import { Observable } from 'rxjs/Observable';
|
||||
templateUrl: './chat-widget.component.html',
|
||||
styleUrls: ['./chat-widget.component.css']
|
||||
})
|
||||
export class ChatWidgetComponent implements OnInit {
|
||||
export class ChatWidgetComponent {
|
||||
chatActive: boolean = false;
|
||||
loading: boolean = false;
|
||||
user: ProfileModel;
|
||||
private user: ProfileModel;
|
||||
messages$: Observable<ChatModel[]>;
|
||||
private messageEl: ElementRef;
|
||||
|
||||
// have to handle ViewChild like this as it's hidden with ngIf
|
||||
@ViewChild('message')
|
||||
set content(content: ElementRef) {
|
||||
this.messageEl = content;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _profileService: ProfileService,
|
||||
@@ -28,25 +34,17 @@ export class ChatWidgetComponent implements OnInit {
|
||||
) {
|
||||
this._profileService.getProfile().subscribe((p) => (this.user = p));
|
||||
this.messages$ = _store.select(fromChat.getChat);
|
||||
this.messages$.subscribe((r) => {
|
||||
if (r.length != 0) {
|
||||
this.chatActive = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
togglePopup() {
|
||||
this.chatActive = !this.chatActive;
|
||||
|
||||
if (this.chatActive && this.user) {
|
||||
this.loading = true;
|
||||
this._signalRService.init('chat').then(() => {
|
||||
this.loading = false;
|
||||
this._signalRService.connection.on('SendMessage', (message) => {
|
||||
console.log(
|
||||
'chat-widget.component',
|
||||
'SendMessage',
|
||||
message
|
||||
);
|
||||
});
|
||||
});
|
||||
if (this.chatActive) {
|
||||
setTimeout(() => this.messageEl.nativeElement.focus(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import * as fromEntriesActions from 'app/actions/entries.actions';
|
||||
import { PodcastService } from '../../../services/podcast.service';
|
||||
import { AudioService } from 'app/services/audio.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { AudioProcessingMessageModel } from 'app/models/audioprocessingmessage.model';
|
||||
|
||||
@Component({
|
||||
selector: '[app-entry-list-item]',
|
||||
@@ -39,23 +40,22 @@ export class EntryListItemComponent implements OnInit {
|
||||
) {
|
||||
this._signalRService
|
||||
.init('audioprocessing')
|
||||
.then(() => {
|
||||
.then((listener) => {
|
||||
const updateChannel: string = `${
|
||||
this.entry.uid
|
||||
}__progress_update`;
|
||||
const processedChannel: string = `${
|
||||
this.entry.uid
|
||||
}__info_processed`;
|
||||
this._signalRService.connection.on(
|
||||
updateChannel,
|
||||
(result) => {
|
||||
listener
|
||||
.on<AudioProcessingMessageModel>(updateChannel)
|
||||
.subscribe((result) => {
|
||||
this.percentageProcessed = result.percentage;
|
||||
this.currentSpeed = result.currentSpeed;
|
||||
}
|
||||
);
|
||||
this._signalRService.connection.on(
|
||||
processedChannel,
|
||||
(result) => {
|
||||
});
|
||||
listener
|
||||
.on<PodcastEntryModel>(processedChannel)
|
||||
.subscribe((result) => {
|
||||
this.entry = result;
|
||||
if (this.entry.processingStatus === 'Processed') {
|
||||
// only update the store when we're finished.
|
||||
@@ -65,8 +65,7 @@ export class EntryListItemComponent implements OnInit {
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch((err) =>
|
||||
console.error(
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
LoadAction,
|
||||
LOAD_FAIL
|
||||
} from './../actions/chat.actions';
|
||||
import { LoadAction, LOAD_FAIL } from './../actions/chat.actions';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Actions, Effect } from '@ngrx/effects';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
@@ -22,17 +19,26 @@ export class ChatEffects {
|
||||
.switchMap((payload: chat.LoadAction) =>
|
||||
this._service
|
||||
.get()
|
||||
.map(res => ({ type: chat.LOAD_SUCCESS, payload: res }))
|
||||
.catch(err => {
|
||||
.map((res) => ({ type: chat.LOAD_SUCCESS, payload: res }))
|
||||
.catch((err) => {
|
||||
console.error('ChatEffects', 'get$', err);
|
||||
return Observable.of({ type: chat.LOAD_FAIL });
|
||||
})
|
||||
);
|
||||
@Effect()
|
||||
put$ = this.actions$
|
||||
.ofType(chat.ADD)
|
||||
.switchMap((action: chat.AddAction) => this._service.send(action.payload))
|
||||
.map(res => ({ type: chat.ADD_SUCCESS, payload: res }));
|
||||
@Effect()
|
||||
put$ = this.actions$
|
||||
.ofType(chat.ADD)
|
||||
.switchMap((action: chat.AddAction) =>
|
||||
this._service.send(action.payload)
|
||||
)
|
||||
.map((res) => ({ type: chat.ADD_SUCCESS, payload: res }));
|
||||
@Effect()
|
||||
receive$ = this.actions$
|
||||
.ofType(chat.RECEIVE)
|
||||
.map((res: chat.ReceiveAction) => ({ type: chat.RECEIVE_SUCCESS, payload: res.payload }));
|
||||
// receive$ = this.actions$.ofType(chat.RECEIVE).map((res) => {
|
||||
// return { type: chat.RECEIVE_SUCCESS, payload: res };
|
||||
// });
|
||||
|
||||
constructor(private _service: ChatService, private actions$: Actions) {}
|
||||
}
|
||||
|
||||
6
client/src/app/models/audioprocessingmessage.model.ts
Normal file
6
client/src/app/models/audioprocessingmessage.model.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export class AudioProcessingMessageModel {
|
||||
percentage: number;
|
||||
totalSize: string;
|
||||
currentSpeed: string;
|
||||
eTA: string;
|
||||
}
|
||||
@@ -33,7 +33,8 @@ export function reducer(state = initialState, action: chat.Actions): State {
|
||||
loading: false
|
||||
};
|
||||
}
|
||||
case chat.ADD_SUCCESS: {
|
||||
case chat.ADD_SUCCESS:
|
||||
case chat.RECEIVE_SUCCESS: {
|
||||
const newResults = _.clone(state.result);
|
||||
newResults.push(action.payload);
|
||||
const newState = {
|
||||
|
||||
@@ -4,11 +4,35 @@ import { Observable } from 'rxjs/Observable';
|
||||
import { environment } from 'environments/environment';
|
||||
import { ChatModel } from 'app/models/chat.model';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { SignalRService } from './signalr.service';
|
||||
import { Subject } from 'rxjs';
|
||||
import * as fromChat from 'app/reducers';
|
||||
import * as fromChatActions from 'app/actions/chat.actions';
|
||||
import { ApplicationState } from '../store';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
@Injectable()
|
||||
export class ChatService extends BaseService {
|
||||
constructor(private _http: HttpClient) {
|
||||
constructor(
|
||||
private _http: HttpClient,
|
||||
private _signalRService: SignalRService,
|
||||
private _store: Store<ApplicationState>
|
||||
) {
|
||||
super();
|
||||
this._signalRService.init('chat').then((listener) => {
|
||||
listener
|
||||
.on<ChatModel>('SendMessage')
|
||||
.subscribe((message: ChatModel) => {
|
||||
console.log(
|
||||
'chat-widget.component',
|
||||
'SendMessage',
|
||||
message
|
||||
);
|
||||
this._store.dispatch(
|
||||
new fromChatActions.ReceiveAction(message)
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get(): Observable<ChatModel[]> {
|
||||
|
||||
@@ -18,7 +18,7 @@ export class MessagingService {
|
||||
private _pushRegistrationServer: PushRegistrationService
|
||||
) {
|
||||
this.messaging.usePublicVapidKey(
|
||||
'BKyhUqIVZLauKNA-DXPXbIVLj5XiWurHbRV_0Rd3BOjY5cU9GOrd5ptXVJ2CNExxdveKYzZevrep2CflKeqkyqo'
|
||||
'BP05eVFzqeEh54DaL3TOe6x_8UFs60nw_gfSrI5tdILjb5VnHwas0n7c_075tsc1w5fm87u9d4Dawj_YN13PSAI'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
import { PodnomsAuthService } from './podnoms-auth.service';
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
HubConnection,
|
||||
HubConnectionBuilder,
|
||||
JsonHubProtocol,
|
||||
LogLevel
|
||||
} from '@aspnet/signalr';
|
||||
import { HubConnection, HubConnectionBuilder, LogLevel } from '@aspnet/signalr';
|
||||
import { environment } from 'environments/environment';
|
||||
import { Observable, Subscriber } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class SignalRService {
|
||||
public connection: HubConnection;
|
||||
private _connected: boolean = false;
|
||||
private _connection: HubConnection;
|
||||
|
||||
constructor(private _auth: PodnomsAuthService) {}
|
||||
public init(hub: string): Promise<void> {
|
||||
const url = `${environment.SIGNALR_HOST}/hubs/${hub}`;
|
||||
public init(hub: string): Promise<SignalRService> {
|
||||
return new Promise((resolve) => {
|
||||
const url = `${environment.SIGNALR_HOST}/hubs/${hub}`;
|
||||
const token = this._auth.getToken();
|
||||
this._connection = new HubConnectionBuilder()
|
||||
.configureLogging(LogLevel.Debug)
|
||||
.withUrl(url + '?token=' + token)
|
||||
.build();
|
||||
resolve(this);
|
||||
});
|
||||
}
|
||||
|
||||
const token = this._auth.getToken();
|
||||
const options: any = {
|
||||
transport: 0
|
||||
};
|
||||
|
||||
this.connection = new HubConnectionBuilder()
|
||||
.configureLogging(LogLevel.Error)
|
||||
.withUrl(url + '?token=' + token, options)
|
||||
.withHubProtocol(new JsonHubProtocol())
|
||||
.build();
|
||||
return this.connection.start();
|
||||
public on<T>(channel: string): Observable<T> {
|
||||
const listener = new Observable<T>((subscriber: Subscriber<T>) => {
|
||||
this._connection.on(channel, (message) => {
|
||||
const result: T = message as T;
|
||||
subscriber.next(result);
|
||||
});
|
||||
});
|
||||
if (!this._connected) {
|
||||
this._connection.start().then(() => (this._connected = true));
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<!-- End Google Analytics -->
|
||||
<!-- Begin Crisp -->
|
||||
<script type="text/javascript">window.$crisp = []; window.CRISP_WEBSITE_ID = "af7d6aa7-0cb8-4f74-89aa-7f3742058e85"; (function () { d = document; s = d.createElement("script"); s.src = "https://client.crisp.chat/l.js"; s.async = 1; d.getElementsByTagName("head")[0].appendChild(s); })();</script>
|
||||
<!-- End Crisp -->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user