Merge branch 'release/1.4.0' into develop
authorChocobozzz <me@florianbigard.com>
Thu, 22 Aug 2019 15:16:48 +0000 (17:16 +0200)
committerChocobozzz <me@florianbigard.com>
Thu, 22 Aug 2019 15:16:48 +0000 (17:16 +0200)
client/angular.json
client/e2e/proxy.config.json [new file with mode: 0644]
client/src/app/+admin/plugins/shared/plugin-list.component.scss
client/src/app/app.component.ts
client/src/app/core/confirm/confirm.service.ts
client/src/app/shared/confirm/confirm.component.ts
client/src/app/shared/misc/constants.ts [new file with mode: 0644]
client/src/app/videos/+video-watch/video-watch.component.ts
server/controllers/lazy-static.ts

index e1e4f4850cb5372542ced50d446403dc5eda3236..950ac059e99a2e2b9ca0ec1a5e10bc595b020a6b 100644 (file)
@@ -86,7 +86,8 @@
           "options": {
             "baseHref": "/",
             "deployUrl": "client/",
-            "browserTarget": "PeerTube:build"
+            "browserTarget": "PeerTube:build",
+            "proxyConfig": "proxy.config.json"
           },
           "configurations": {
             "production": {
@@ -96,7 +97,8 @@
               "browserTarget": "PeerTube:build:hmr"
             },
             "e2e": {
-              "browserTarget": "PeerTube:build:e2e"
+              "browserTarget": "PeerTube:build:e2e",
+              "proxyConfig": "e2e/proxy.config.json"
             }
           }
         },
diff --git a/client/e2e/proxy.config.json b/client/e2e/proxy.config.json
new file mode 100644 (file)
index 0000000..00bda5e
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  "/api": {
+    "target": "http://localhost:9000",
+    "secure": false
+  },
+  "/plugins": {
+    "target": "http://localhost:9000",
+    "secure": false
+  },
+  "/themes": {
+    "target": "http://localhost:9000",
+    "secure": false
+  },
+  "/static": {
+    "target": "http://localhost:9000",
+    "secure": false
+  },
+  "/lazy-static": {
+    "target": "http://localhost:9000",
+    "secure": false
+  },
+  "/socket.io": {
+    "target": "ws://localhost:9000",
+    "secure": false,
+    "ws": true
+  },
+  "/!(client)**": {
+    "target": "http://localhost:3333/client/index.html",
+    "secure": false,
+    "logLevel": "debug"
+  },
+  "/!(client)**/**": {
+    "target": "http://localhost:3333/client/index.html",
+    "secure": false,
+    "logLevel": "debug"
+  }
+}
index f1516240e7ce2294002c43b0edd1fe210468a9df..3663d3fddf2fc3f9e3bc0e03e157996a3431972b 100644 (file)
@@ -3,6 +3,7 @@
 
 .plugin {
   margin: 15px 0;
+  background-color: var(--submenuColor);
 }
 
 .first-row {
index 50c5f5b9bb41ba3755be7abaf415bfc8f7bd5d4f..64bfb9671bf9a9b20f521bb4c2dae8bbb31d9414 100644 (file)
@@ -8,9 +8,11 @@ import { debounceTime, filter, map, pairwise, skip } from 'rxjs/operators'
 import { Hotkey, HotkeysService } from 'angular2-hotkeys'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { fromEvent } from 'rxjs'
-import { ViewportScroller } from '@angular/common'
+import { PlatformLocation, ViewportScroller } from '@angular/common'
 import { PluginService } from '@app/core/plugins/plugin.service'
 import { HooksService } from '@app/core/plugins/hooks.service'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants'
 
 @Component({
   selector: 'my-app',
@@ -35,7 +37,9 @@ export class AppComponent implements OnInit {
     private screenService: ScreenService,
     private hotkeysService: HotkeysService,
     private themeService: ThemeService,
-    private hooks: HooksService
+    private hooks: HooksService,
+    private location: PlatformLocation,
+    private modalService: NgbModal
   ) { }
 
   get serverVersion () {
@@ -90,6 +94,8 @@ export class AppComponent implements OnInit {
     fromEvent(window, 'resize')
       .pipe(debounceTime(200))
       .subscribe(() => this.onResize())
+
+    this.location.onPopState(() => this.modalService.dismissAll(POP_STATE_MODAL_DISMISS))
   }
 
   isUserLoggedIn () {
@@ -110,7 +116,6 @@ export class AppComponent implements OnInit {
     const eventsObs = this.router.events
 
     const scrollEvent = eventsObs.pipe(filter((e: Event): e is Scroll => e instanceof Scroll))
-    const navigationEndEvent = eventsObs.pipe(filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd))
 
     scrollEvent.subscribe(e => {
       if (e.position) {
@@ -126,6 +131,8 @@ export class AppComponent implements OnInit {
       }
     })
 
+    const navigationEndEvent = eventsObs.pipe(filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd))
+
     // When we add the a-state parameter, we don't want to alter the scroll
     navigationEndEvent.pipe(pairwise())
                       .subscribe(([ e1, e2 ]) => {
index 8419f622b257e0afd395a24f780f554e3449e088..6e042c16bf5f99485b0b58efdcc749e65a52b5f9 100644 (file)
@@ -18,12 +18,16 @@ export class ConfirmService {
   confirm (message: string, title = '', confirmButtonText?: string) {
     this.showConfirm.next({ title, message, confirmButtonText })
 
-    return this.confirmResponse.asObservable().pipe(first()).toPromise()
+    return this.confirmResponse.asObservable()
+               .pipe(first())
+               .toPromise()
   }
 
   confirmWithInput (message: string, inputLabel: string, expectedInputValue: string, title = '', confirmButtonText?: string) {
     this.showConfirm.next({ title, message, inputLabel, expectedInputValue, confirmButtonText })
 
-    return this.confirmResponse.asObservable().pipe(first()).toPromise()
+    return this.confirmResponse.asObservable()
+               .pipe(first())
+               .toPromise()
   }
 }
index 53aed14d7bf649b7823875a3ecb37b28594bb19f..763454c4f8c9c2d88ec7610d9e3306458facfbb1 100644 (file)
@@ -3,6 +3,7 @@ import { ConfirmService } from '@app/core/confirm/confirm.service'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
+import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants'
 
 @Component({
   selector: 'my-confirm',
@@ -63,6 +64,11 @@ export class ConfirmComponent implements OnInit {
 
     this.openedModal.result
         .then(() => this.confirmService.confirmResponse.next(true))
-        .catch(() => this.confirmService.confirmResponse.next(false))
+        .catch((reason: string) => {
+          // If the reason was that the user used the back button, we don't care about the confirm dialog result
+          if (!reason || reason !== POP_STATE_MODAL_DISMISS) {
+            this.confirmService.confirmResponse.next(false)
+          }
+        })
   }
 }
diff --git a/client/src/app/shared/misc/constants.ts b/client/src/app/shared/misc/constants.ts
new file mode 100644 (file)
index 0000000..bb4a088
--- /dev/null
@@ -0,0 +1 @@
+export const POP_STATE_MODAL_DISMISS = 'pop state dismiss'
index d7c7b74971dfd1ad8f67cc73e79c5d7defa071d6..21a24113fa9c0ae4916155b4fed508ec2cede124 100644 (file)
@@ -34,6 +34,7 @@ import { VideoWatchPlaylistComponent } from '@app/videos/+video-watch/video-watc
 import { getStoredTheater } from '../../../assets/player/peertube-player-local-storage'
 import { PluginService } from '@app/core/plugins/plugin.service'
 import { HooksService } from '@app/core/plugins/hooks.service'
+import { PlatformLocation } from '@angular/common'
 
 @Component({
   selector: 'my-video-watch',
@@ -95,6 +96,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     private i18n: I18n,
     private hotkeysService: HotkeysService,
     private hooks: HooksService,
+    private location: PlatformLocation,
     @Inject(LOCALE_ID) private localeId: string
   ) {}
 
@@ -374,13 +376,13 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
         this.i18n('This video contains mature or explicit content. Are you sure you want to watch it?'),
         this.i18n('Mature or explicit content')
       )
-      if (res === false) return this.redirectService.redirectToHomepage()
+      if (res === false) return this.location.back()
     }
 
     // Flush old player if needed
     this.flushPlayer()
 
-    // Build video element, because videojs remove it on dispose
+    // Build video element, because videojs removes it on dispose
     const playerElementWrapper = this.elementRef.nativeElement.querySelector('#videojs-wrapper')
     this.playerElement = document.createElement('video')
     this.playerElement.className = 'video-js vjs-peertube-skin'
index 28d2f862a59008f3df9f24c5545e830e170772cd..1ff99e90c2830f76ce98ab2b40d105dcd96c88f0 100644 (file)
@@ -44,6 +44,8 @@ async function getAvatar (req: express.Request, res: express.Response) {
   }
 
   const avatar = await AvatarModel.loadByName(filename)
+  if (!avatar) return res.sendStatus(404)
+
   if (avatar.onDisk === false) {
     if (!avatar.fileUrl) return res.sendStatus(404)