diff options
-rw-r--r-- | client/angular.json | 6 | ||||
-rw-r--r-- | client/e2e/proxy.config.json | 37 | ||||
-rw-r--r-- | client/src/app/+admin/plugins/shared/plugin-list.component.scss | 1 | ||||
-rw-r--r-- | client/src/app/app.component.ts | 13 | ||||
-rw-r--r-- | client/src/app/core/confirm/confirm.service.ts | 8 | ||||
-rw-r--r-- | client/src/app/shared/confirm/confirm.component.ts | 8 | ||||
-rw-r--r-- | client/src/app/shared/misc/constants.ts | 1 | ||||
-rw-r--r-- | client/src/app/videos/+video-watch/video-watch.component.ts | 6 | ||||
-rw-r--r-- | server/controllers/lazy-static.ts | 2 |
9 files changed, 72 insertions, 10 deletions
diff --git a/client/angular.json b/client/angular.json index e1e4f4850..950ac059e 100644 --- a/client/angular.json +++ b/client/angular.json | |||
@@ -86,7 +86,8 @@ | |||
86 | "options": { | 86 | "options": { |
87 | "baseHref": "/", | 87 | "baseHref": "/", |
88 | "deployUrl": "client/", | 88 | "deployUrl": "client/", |
89 | "browserTarget": "PeerTube:build" | 89 | "browserTarget": "PeerTube:build", |
90 | "proxyConfig": "proxy.config.json" | ||
90 | }, | 91 | }, |
91 | "configurations": { | 92 | "configurations": { |
92 | "production": { | 93 | "production": { |
@@ -96,7 +97,8 @@ | |||
96 | "browserTarget": "PeerTube:build:hmr" | 97 | "browserTarget": "PeerTube:build:hmr" |
97 | }, | 98 | }, |
98 | "e2e": { | 99 | "e2e": { |
99 | "browserTarget": "PeerTube:build:e2e" | 100 | "browserTarget": "PeerTube:build:e2e", |
101 | "proxyConfig": "e2e/proxy.config.json" | ||
100 | } | 102 | } |
101 | } | 103 | } |
102 | }, | 104 | }, |
diff --git a/client/e2e/proxy.config.json b/client/e2e/proxy.config.json new file mode 100644 index 000000000..00bda5eb7 --- /dev/null +++ b/client/e2e/proxy.config.json | |||
@@ -0,0 +1,37 @@ | |||
1 | { | ||
2 | "/api": { | ||
3 | "target": "http://localhost:9000", | ||
4 | "secure": false | ||
5 | }, | ||
6 | "/plugins": { | ||
7 | "target": "http://localhost:9000", | ||
8 | "secure": false | ||
9 | }, | ||
10 | "/themes": { | ||
11 | "target": "http://localhost:9000", | ||
12 | "secure": false | ||
13 | }, | ||
14 | "/static": { | ||
15 | "target": "http://localhost:9000", | ||
16 | "secure": false | ||
17 | }, | ||
18 | "/lazy-static": { | ||
19 | "target": "http://localhost:9000", | ||
20 | "secure": false | ||
21 | }, | ||
22 | "/socket.io": { | ||
23 | "target": "ws://localhost:9000", | ||
24 | "secure": false, | ||
25 | "ws": true | ||
26 | }, | ||
27 | "/!(client)**": { | ||
28 | "target": "http://localhost:3333/client/index.html", | ||
29 | "secure": false, | ||
30 | "logLevel": "debug" | ||
31 | }, | ||
32 | "/!(client)**/**": { | ||
33 | "target": "http://localhost:3333/client/index.html", | ||
34 | "secure": false, | ||
35 | "logLevel": "debug" | ||
36 | } | ||
37 | } | ||
diff --git a/client/src/app/+admin/plugins/shared/plugin-list.component.scss b/client/src/app/+admin/plugins/shared/plugin-list.component.scss index f1516240e..3663d3fdd 100644 --- a/client/src/app/+admin/plugins/shared/plugin-list.component.scss +++ b/client/src/app/+admin/plugins/shared/plugin-list.component.scss | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | .plugin { | 4 | .plugin { |
5 | margin: 15px 0; | 5 | margin: 15px 0; |
6 | background-color: var(--submenuColor); | ||
6 | } | 7 | } |
7 | 8 | ||
8 | .first-row { | 9 | .first-row { |
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index 50c5f5b9b..64bfb9671 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts | |||
@@ -8,9 +8,11 @@ import { debounceTime, filter, map, pairwise, skip } from 'rxjs/operators' | |||
8 | import { Hotkey, HotkeysService } from 'angular2-hotkeys' | 8 | import { Hotkey, HotkeysService } from 'angular2-hotkeys' |
9 | import { I18n } from '@ngx-translate/i18n-polyfill' | 9 | import { I18n } from '@ngx-translate/i18n-polyfill' |
10 | import { fromEvent } from 'rxjs' | 10 | import { fromEvent } from 'rxjs' |
11 | import { ViewportScroller } from '@angular/common' | 11 | import { PlatformLocation, ViewportScroller } from '@angular/common' |
12 | import { PluginService } from '@app/core/plugins/plugin.service' | 12 | import { PluginService } from '@app/core/plugins/plugin.service' |
13 | import { HooksService } from '@app/core/plugins/hooks.service' | 13 | import { HooksService } from '@app/core/plugins/hooks.service' |
14 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | ||
15 | import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants' | ||
14 | 16 | ||
15 | @Component({ | 17 | @Component({ |
16 | selector: 'my-app', | 18 | selector: 'my-app', |
@@ -35,7 +37,9 @@ export class AppComponent implements OnInit { | |||
35 | private screenService: ScreenService, | 37 | private screenService: ScreenService, |
36 | private hotkeysService: HotkeysService, | 38 | private hotkeysService: HotkeysService, |
37 | private themeService: ThemeService, | 39 | private themeService: ThemeService, |
38 | private hooks: HooksService | 40 | private hooks: HooksService, |
41 | private location: PlatformLocation, | ||
42 | private modalService: NgbModal | ||
39 | ) { } | 43 | ) { } |
40 | 44 | ||
41 | get serverVersion () { | 45 | get serverVersion () { |
@@ -90,6 +94,8 @@ export class AppComponent implements OnInit { | |||
90 | fromEvent(window, 'resize') | 94 | fromEvent(window, 'resize') |
91 | .pipe(debounceTime(200)) | 95 | .pipe(debounceTime(200)) |
92 | .subscribe(() => this.onResize()) | 96 | .subscribe(() => this.onResize()) |
97 | |||
98 | this.location.onPopState(() => this.modalService.dismissAll(POP_STATE_MODAL_DISMISS)) | ||
93 | } | 99 | } |
94 | 100 | ||
95 | isUserLoggedIn () { | 101 | isUserLoggedIn () { |
@@ -110,7 +116,6 @@ export class AppComponent implements OnInit { | |||
110 | const eventsObs = this.router.events | 116 | const eventsObs = this.router.events |
111 | 117 | ||
112 | const scrollEvent = eventsObs.pipe(filter((e: Event): e is Scroll => e instanceof Scroll)) | 118 | const scrollEvent = eventsObs.pipe(filter((e: Event): e is Scroll => e instanceof Scroll)) |
113 | const navigationEndEvent = eventsObs.pipe(filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd)) | ||
114 | 119 | ||
115 | scrollEvent.subscribe(e => { | 120 | scrollEvent.subscribe(e => { |
116 | if (e.position) { | 121 | if (e.position) { |
@@ -126,6 +131,8 @@ export class AppComponent implements OnInit { | |||
126 | } | 131 | } |
127 | }) | 132 | }) |
128 | 133 | ||
134 | const navigationEndEvent = eventsObs.pipe(filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd)) | ||
135 | |||
129 | // When we add the a-state parameter, we don't want to alter the scroll | 136 | // When we add the a-state parameter, we don't want to alter the scroll |
130 | navigationEndEvent.pipe(pairwise()) | 137 | navigationEndEvent.pipe(pairwise()) |
131 | .subscribe(([ e1, e2 ]) => { | 138 | .subscribe(([ e1, e2 ]) => { |
diff --git a/client/src/app/core/confirm/confirm.service.ts b/client/src/app/core/confirm/confirm.service.ts index 8419f622b..6e042c16b 100644 --- a/client/src/app/core/confirm/confirm.service.ts +++ b/client/src/app/core/confirm/confirm.service.ts | |||
@@ -18,12 +18,16 @@ export class ConfirmService { | |||
18 | confirm (message: string, title = '', confirmButtonText?: string) { | 18 | confirm (message: string, title = '', confirmButtonText?: string) { |
19 | this.showConfirm.next({ title, message, confirmButtonText }) | 19 | this.showConfirm.next({ title, message, confirmButtonText }) |
20 | 20 | ||
21 | return this.confirmResponse.asObservable().pipe(first()).toPromise() | 21 | return this.confirmResponse.asObservable() |
22 | .pipe(first()) | ||
23 | .toPromise() | ||
22 | } | 24 | } |
23 | 25 | ||
24 | confirmWithInput (message: string, inputLabel: string, expectedInputValue: string, title = '', confirmButtonText?: string) { | 26 | confirmWithInput (message: string, inputLabel: string, expectedInputValue: string, title = '', confirmButtonText?: string) { |
25 | this.showConfirm.next({ title, message, inputLabel, expectedInputValue, confirmButtonText }) | 27 | this.showConfirm.next({ title, message, inputLabel, expectedInputValue, confirmButtonText }) |
26 | 28 | ||
27 | return this.confirmResponse.asObservable().pipe(first()).toPromise() | 29 | return this.confirmResponse.asObservable() |
30 | .pipe(first()) | ||
31 | .toPromise() | ||
28 | } | 32 | } |
29 | } | 33 | } |
diff --git a/client/src/app/shared/confirm/confirm.component.ts b/client/src/app/shared/confirm/confirm.component.ts index 53aed14d7..763454c4f 100644 --- a/client/src/app/shared/confirm/confirm.component.ts +++ b/client/src/app/shared/confirm/confirm.component.ts | |||
@@ -3,6 +3,7 @@ import { ConfirmService } from '@app/core/confirm/confirm.service' | |||
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | 3 | import { I18n } from '@ngx-translate/i18n-polyfill' |
4 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | 4 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' |
5 | import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' | 5 | import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' |
6 | import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants' | ||
6 | 7 | ||
7 | @Component({ | 8 | @Component({ |
8 | selector: 'my-confirm', | 9 | selector: 'my-confirm', |
@@ -63,6 +64,11 @@ export class ConfirmComponent implements OnInit { | |||
63 | 64 | ||
64 | this.openedModal.result | 65 | this.openedModal.result |
65 | .then(() => this.confirmService.confirmResponse.next(true)) | 66 | .then(() => this.confirmService.confirmResponse.next(true)) |
66 | .catch(() => this.confirmService.confirmResponse.next(false)) | 67 | .catch((reason: string) => { |
68 | // If the reason was that the user used the back button, we don't care about the confirm dialog result | ||
69 | if (!reason || reason !== POP_STATE_MODAL_DISMISS) { | ||
70 | this.confirmService.confirmResponse.next(false) | ||
71 | } | ||
72 | }) | ||
67 | } | 73 | } |
68 | } | 74 | } |
diff --git a/client/src/app/shared/misc/constants.ts b/client/src/app/shared/misc/constants.ts new file mode 100644 index 000000000..bb4a0884e --- /dev/null +++ b/client/src/app/shared/misc/constants.ts | |||
@@ -0,0 +1 @@ | |||
export const POP_STATE_MODAL_DISMISS = 'pop state dismiss' | |||
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index d7c7b7497..21a24113f 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -34,6 +34,7 @@ import { VideoWatchPlaylistComponent } from '@app/videos/+video-watch/video-watc | |||
34 | import { getStoredTheater } from '../../../assets/player/peertube-player-local-storage' | 34 | import { getStoredTheater } from '../../../assets/player/peertube-player-local-storage' |
35 | import { PluginService } from '@app/core/plugins/plugin.service' | 35 | import { PluginService } from '@app/core/plugins/plugin.service' |
36 | import { HooksService } from '@app/core/plugins/hooks.service' | 36 | import { HooksService } from '@app/core/plugins/hooks.service' |
37 | import { PlatformLocation } from '@angular/common' | ||
37 | 38 | ||
38 | @Component({ | 39 | @Component({ |
39 | selector: 'my-video-watch', | 40 | selector: 'my-video-watch', |
@@ -95,6 +96,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
95 | private i18n: I18n, | 96 | private i18n: I18n, |
96 | private hotkeysService: HotkeysService, | 97 | private hotkeysService: HotkeysService, |
97 | private hooks: HooksService, | 98 | private hooks: HooksService, |
99 | private location: PlatformLocation, | ||
98 | @Inject(LOCALE_ID) private localeId: string | 100 | @Inject(LOCALE_ID) private localeId: string |
99 | ) {} | 101 | ) {} |
100 | 102 | ||
@@ -374,13 +376,13 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
374 | this.i18n('This video contains mature or explicit content. Are you sure you want to watch it?'), | 376 | this.i18n('This video contains mature or explicit content. Are you sure you want to watch it?'), |
375 | this.i18n('Mature or explicit content') | 377 | this.i18n('Mature or explicit content') |
376 | ) | 378 | ) |
377 | if (res === false) return this.redirectService.redirectToHomepage() | 379 | if (res === false) return this.location.back() |
378 | } | 380 | } |
379 | 381 | ||
380 | // Flush old player if needed | 382 | // Flush old player if needed |
381 | this.flushPlayer() | 383 | this.flushPlayer() |
382 | 384 | ||
383 | // Build video element, because videojs remove it on dispose | 385 | // Build video element, because videojs removes it on dispose |
384 | const playerElementWrapper = this.elementRef.nativeElement.querySelector('#videojs-wrapper') | 386 | const playerElementWrapper = this.elementRef.nativeElement.querySelector('#videojs-wrapper') |
385 | this.playerElement = document.createElement('video') | 387 | this.playerElement = document.createElement('video') |
386 | this.playerElement.className = 'video-js vjs-peertube-skin' | 388 | this.playerElement.className = 'video-js vjs-peertube-skin' |
diff --git a/server/controllers/lazy-static.ts b/server/controllers/lazy-static.ts index 28d2f862a..1ff99e90c 100644 --- a/server/controllers/lazy-static.ts +++ b/server/controllers/lazy-static.ts | |||
@@ -44,6 +44,8 @@ async function getAvatar (req: express.Request, res: express.Response) { | |||
44 | } | 44 | } |
45 | 45 | ||
46 | const avatar = await AvatarModel.loadByName(filename) | 46 | const avatar = await AvatarModel.loadByName(filename) |
47 | if (!avatar) return res.sendStatus(404) | ||
48 | |||
47 | if (avatar.onDisk === false) { | 49 | if (avatar.onDisk === false) { |
48 | if (!avatar.fileUrl) return res.sendStatus(404) | 50 | if (!avatar.fileUrl) return res.sendStatus(404) |
49 | 51 | ||