Compare commits

...
6 Commits
Author SHA1 Message Date
death-claw 5fd70a821b v1.6.3 2019-09-18 19:44:45 +01:00
death-claw 6e9c912118 Better multithread management
Fix partial state UI
2019-09-18 19:41:48 +01:00
death-claw 19a98ea056 v1.6.2 2019-09-17 23:00:55 +01:00
death-claw 229bc46227 Rework UI colors
Fix scan input bug
2019-09-17 22:59:04 +01:00
death-claw 374946c6f2 v1.6.1 2019-09-16 22:56:57 +01:00
death-claw f8eccfb4ad Rework UI
Fix clipboard monitoring
2019-09-16 22:54:18 +01:00
28 changed files with 366 additions and 273 deletions
+15
View File
@@ -1,5 +1,20 @@
# Changelog
## [1.6.3] - 2019-09-18
### Changed
- Better multithread management
- Fix partial state UI
## [1.6.2] - 2019-09-17
### Changed
- Rework UI colors
- Fix scan input bug
## [1.6.1] - 2019-09-16
### Changed
- Rework UI
- Fix clipboard monitoring
## [1.6.0] - 2019-09-15
### Changed
- Rework the UI
+1 -1
View File
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>tn.mnlr</groupId>
<artifactId>vripper</artifactId>
<version>1.6.0</version>
<version>1.6.3</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vripper-electron",
"version": "1.6.0",
"version": "1.6.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vripper-electron",
"version": "1.6.0",
"version": "1.6.3",
"description": "",
"main": "main.js",
"author": "",
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>tn.mnlr</groupId>
<artifactId>vripper</artifactId>
<version>1.6.0</version>
<version>1.6.3</version>
</parent>
<artifactId>vripper-electron</artifactId>
<name>vripper-electron</name>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>tn.mnlr</groupId>
<artifactId>vripper</artifactId>
<version>1.6.0</version>
<version>1.6.3</version>
</parent>
<artifactId>vripper-server</artifactId>
<name>vripper-server</name>
@@ -34,12 +34,14 @@ public class DownloadQ {
@Getter
private boolean notPauseQ = true;
public synchronized void put(Image image) throws InterruptedException {
logger.info(String.format("Enqueuing a job for %s", image.getUrl()));
image.init();
DownloadJob downloadJob = new DownloadJob(image);
downloadQ.put(downloadJob);
appStateService.newDownloadJob(downloadJob);
public void put(Image image) throws InterruptedException {
synchronized (appStateService) {
logger.info(String.format("Enqueuing a job for %s", image.getUrl()));
image.init();
DownloadJob downloadJob = new DownloadJob(image);
downloadQ.put(downloadJob);
appStateService.newDownloadJob(downloadJob);
}
}
public DownloadJob take() throws InterruptedException {
@@ -48,69 +50,18 @@ public class DownloadQ {
return downloadJob;
}
public void enqueue(Post post) throws InterruptedException {
public synchronized void enqueue(Post post) throws InterruptedException {
for (Image image : post.getImages()) {
put(image);
}
}
public void restart(String postId) throws InterruptedException {
if (appStateService.getRunningPosts().get(postId) != null && appStateService.getRunningPosts().get(postId).get() > 0) {
logger.warn(String.format("Cannot restart, jobs are currently running for post id %s", postId));
return;
}
List<Image> images = appStateService.getPost(postId)
.getImages()
.stream()
.filter(e -> !e.getStatus().equals(Image.Status.COMPLETE))
.collect(Collectors.toList());
if (images.isEmpty()) {
return;
}
appStateService.getPost(postId).setStatus(Post.Status.PENDING);
logger.info(String.format("Restarting %d jobs for post id %s", images.size(), postId));
for (Image image : images) {
put(image);
}
}
public void removeScheduled(Image image) {
image.setStatus(Image.Status.STOPPED);
logger.info(String.format("Removing scheduled job for %s", image.getUrl()));
Iterator<DownloadJob> iterator = downloadQ.iterator();
boolean removed = false;
while(iterator.hasNext()) {
DownloadJob next = iterator.next();
if(next.getImage().getPostId().equals(image.getPostId())) {
iterator.remove();
appStateService.doneDownloadJob(image);
logger.info(String.format("Scheduled job for %s is removed", image.getUrl()));
removed = true;
break;
}
}
if(!removed) {
logger.warn(String.format("Job for %s does not exist", image.getUrl()));
}
image.cleanup();
}
public void removeRunning(String postId) {
logger.info(String.format("Interrupting running jobs for post id %s", postId));
executionService.stop(postId);
}
public synchronized void stop(String postId) {
try {
if (FINISHED.contains(appStateService.getPost(postId).getStatus())) {
synchronized (appStateService) {
if (appStateService.getRunningPosts().get(postId) != null && appStateService.getRunningPosts().get(postId).get() > 0) {
logger.warn(String.format("Cannot restart, jobs are currently running for post id %s", postId));
return;
}
notPauseQ = false;
appStateService.getPost(postId).setStatus(Post.Status.STOPPED);
List<Image> images = appStateService.getPost(postId)
.getImages()
.stream()
@@ -119,9 +70,66 @@ public class DownloadQ {
if (images.isEmpty()) {
return;
}
logger.info(String.format("Stopping %d jobs for post id %s", images.size(), postId));
images.forEach(image -> removeScheduled(image));
removeRunning(postId);
appStateService.getPost(postId).setStatus(Post.Status.PENDING);
logger.info(String.format("Restarting %d jobs for post id %s", images.size(), postId));
for (Image image : images) {
put(image);
}
}
}
public void removeScheduled(Image image) {
synchronized (appStateService) {
image.setStatus(Image.Status.STOPPED);
logger.info(String.format("Removing scheduled job for %s", image.getUrl()));
Iterator<DownloadJob> iterator = downloadQ.iterator();
boolean removed = false;
while (iterator.hasNext()) {
DownloadJob next = iterator.next();
if (next.getImage().getPostId().equals(image.getPostId())) {
iterator.remove();
appStateService.doneDownloadJob(image);
logger.info(String.format("Scheduled job for %s is removed", image.getUrl()));
removed = true;
break;
}
}
if (!removed) {
logger.warn(String.format("Job for %s does not exist", image.getUrl()));
}
image.cleanup();
}
}
public void removeRunning(String postId) {
logger.info(String.format("Interrupting running jobs for post id %s", postId));
executionService.stop(postId);
}
public void stop(String postId) {
try {
synchronized (appStateService) {
if (FINISHED.contains(appStateService.getPost(postId).getStatus())) {
return;
}
notPauseQ = false;
appStateService.getPost(postId).setStatus(Post.Status.STOPPED);
List<Image> images = appStateService.getPost(postId)
.getImages()
.stream()
.filter(e -> !e.getStatus().equals(Image.Status.COMPLETE))
.collect(Collectors.toList());
if (images.isEmpty()) {
return;
}
logger.info(String.format("Stopping %d jobs for post id %s", images.size(), postId));
images.forEach(image -> removeScheduled(image));
removeRunning(postId);
}
} finally {
notPauseQ = true;
}
@@ -131,14 +139,18 @@ public class DownloadQ {
return downloadQ.size();
}
public synchronized void stopAll() {
appStateService.getCurrentPosts().values().stream().map(Post::getPostId).forEach(this::stop);
public void stopAll() {
synchronized (appStateService) {
appStateService.getCurrentPosts().values().stream().map(Post::getPostId).forEach(this::stop);
}
}
public synchronized void restartAll() throws InterruptedException {
for (Post post : appStateService.getCurrentPosts().values()) {
String postId = post.getPostId();
restart(postId);
public void restartAll() throws InterruptedException {
synchronized (appStateService) {
for (Post post : appStateService.getCurrentPosts().values()) {
String postId = post.getPostId();
restart(postId);
}
}
}
}
@@ -34,9 +34,10 @@ public class SettingsRestEndpoint {
@PostMapping("/settings/theme")
@ResponseStatus(value = HttpStatus.OK)
public AppSettingsService.Theme postTheme(@RequestBody AppSettingsService.Theme theme) {
this.settings.setTheme(theme);
return settings.getTheme();
synchronized (this.settings) {
this.settings.setTheme(theme);
return settings.getTheme();
}
}
@GetMapping("/settings/theme")
@@ -49,33 +50,35 @@ public class SettingsRestEndpoint {
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity postSettings(@RequestBody AppSettingsService.Settings settings) throws Exception {
try {
this.settings.check(settings);
} catch (ValidationException e) {
return new ResponseEntity(new Response(e.getMessage()), HttpStatus.BAD_REQUEST);
}
this.settings.setDownloadPath(settings.getDownloadPath());
this.settings.setMaxThreads(settings.getMaxThreads());
this.settings.setAutoStart(settings.isAutoStart());
this.settings.setVLogin(settings.isVLogin());
if(settings.isVLogin()) {
this.settings.setVUsername(settings.getVUsername());
if (!this.settings.getVPassword().equals(settings.getVPassword())) {
this.settings.setVPassword(settings.getVPassword());
synchronized (this.settings) {
try {
this.settings.check(settings);
} catch (ValidationException e) {
return new ResponseEntity(new Response(e.getMessage()), HttpStatus.BAD_REQUEST);
}
this.settings.setVThanks(settings.isVThanks());
} else {
this.settings.setVUsername("");
this.settings.setVPassword("");
this.settings.setVThanks(false);
this.settings.setDownloadPath(settings.getDownloadPath());
this.settings.setMaxThreads(settings.getMaxThreads());
this.settings.setAutoStart(settings.isAutoStart());
this.settings.setVLogin(settings.isVLogin());
if (settings.isVLogin()) {
this.settings.setVUsername(settings.getVUsername());
if (!this.settings.getVPassword().equals(settings.getVPassword())) {
this.settings.setVPassword(settings.getVPassword());
}
this.settings.setVThanks(settings.isVThanks());
} else {
this.settings.setVUsername("");
this.settings.setVPassword("");
this.settings.setVThanks(false);
}
this.settings.setDesktopClipboard(settings.isDesktopClipboard());
this.settings.setForceOrder(settings.isForceOrder());
this.settings.save();
vipergirlsAuthService.authenticate();
}
this.settings.setDesktopClipboard(settings.isDesktopClipboard());
this.settings.setForceOrder(settings.isForceOrder());
this.settings.save();
vipergirlsAuthService.authenticate();
return ResponseEntity.ok(getSettings());
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vripper-ui",
"version": "1.6.0",
"version": "1.6.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vripper-ui",
"version": "1.6.0",
"version": "1.6.3",
"scripts": {
"ng": "ng",
"start": "ng serve",
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>tn.mnlr</groupId>
<artifactId>vripper</artifactId>
<version>1.6.0</version>
<version>1.6.3</version>
</parent>
<artifactId>vripper-ui</artifactId>
<name>vripper-ui</name>
@@ -1,17 +1,8 @@
@import '~@angular/material/theming';
// mixin name will be used in main style.scss
@mixin app-component-theme($theme) {
// retrieve variables from theme
// (all possible variables, use only what you really need)
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, accent);
$foreground: map-get($theme, foreground);
$background: map-get($theme, background);
// all of these variables contain many additional variables
button.add-button {
+1 -7
View File
@@ -16,7 +16,6 @@ import { RemoveAllResponse } from './common/remove-all-response.model';
import { ServerService } from './server-service';
import { ConfirmDialogComponent } from './common/confirmation-component/confirmation-dialog';
import { filter, flatMap } from 'rxjs/operators';
import { ScanComponent } from './scan/scan.component';
@Component({
selector: 'app-root',
@@ -52,12 +51,7 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
}
scan() {
const dialogRef = this.dialog.open(ScanComponent, {
width: '70%',
height: '70%',
maxWidth: '100vw',
maxHeight: '100vh'
});
this.appService.scan();
}
openSettings(): void {
+48 -11
View File
@@ -1,12 +1,20 @@
import { MatDialog } from '@angular/material';
import { HttpClient } from '@angular/common/http';
import { Injectable, Renderer2 } from '@angular/core';
import { Injectable, Renderer2, NgZone } from '@angular/core';
import { ServerService } from './server-service';
import { tap } from 'rxjs/operators';
import { ScanComponent } from './scan/scan.component';
import { Observable } from 'rxjs';
import { BreakpointState, Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
@Injectable()
export class AppService {
constructor(private httpClient: HttpClient, private serverService: ServerService) {}
constructor(
private httpClient: HttpClient,
private serverService: ServerService,
public dialog: MatDialog,
private breakpointObserver: BreakpointObserver,
) {}
darkTheme = false;
_renderer: Renderer2;
@@ -14,6 +22,9 @@ export class AppService {
this._renderer = renderer;
}
isExtraSmall: Observable<BreakpointState> = this.breakpointObserver.observe(Breakpoints.XSmall);
isScanOpen = false;
updateTheme(darkTheme: boolean) {
this.darkTheme = darkTheme;
if (this.darkTheme) {
@@ -23,20 +34,46 @@ export class AppService {
this._renderer.addClass(document.body, 'light-theme');
this._renderer.removeClass(document.body, 'dark-theme');
}
this.httpClient.post<Theme>(this.serverService.baseUrl + '/settings/theme', {
darkTheme: this.darkTheme
}).subscribe();
this.httpClient
.post<Theme>(this.serverService.baseUrl + '/settings/theme', {
darkTheme: this.darkTheme
})
.subscribe();
}
loadTheme() {
return this.httpClient
.get<Theme>(this.serverService.baseUrl + '/settings/theme')
.pipe(
tap(theme => this.updateTheme(theme.darkTheme))
);
.get<Theme>(this.serverService.baseUrl + '/settings/theme')
.pipe(tap(theme => this.updateTheme(theme.darkTheme)));
}
scan(url?: string) {
const scanDialog = this.dialog.open(ScanComponent, {
width: '70%',
height: '70%',
maxWidth: '100vw',
maxHeight: '100vh',
data: {url: url}
});
const smallDialogSubscription = this.isExtraSmall.subscribe(result => {
if (result.matches) {
scanDialog.updateSize('100%', '100%');
} else {
scanDialog.updateSize('70%', '70%');
}
});
scanDialog.afterOpened().subscribe(() => this.isScanOpen = true);
scanDialog.afterClosed().subscribe(() => {
smallDialogSubscription.unsubscribe();
this.isScanOpen = false;
});
}
}
export interface Theme {
darkTheme: boolean;
}
}
+16 -10
View File
@@ -1,7 +1,8 @@
import { AppService } from './../app.service';
import { ElectronService } from 'ngx-electron';
import { ClipboardService } from './../clipboard.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Component, OnInit, OnDestroy, NgZone } from '@angular/core';
import { MatDialog, MatSnackBar } from '@angular/material';
import { WsConnectionService } from '../ws-connection.service';
import { WsHandler } from '../ws-handler';
import { Subscription } from 'rxjs';
@@ -23,7 +24,10 @@ export class HomeComponent implements OnInit, OnDestroy {
private clipboardService: ClipboardService,
public dialog: MatDialog,
public electronService: ElectronService,
private wsConnectionService: WsConnectionService
private wsConnectionService: WsConnectionService,
private appService: AppService,
private _snackBar: MatSnackBar,
private ngZone: NgZone
) {
this.websocketHandlerPromise = this.wsConnectionService.getConnection();
}
@@ -32,13 +36,15 @@ export class HomeComponent implements OnInit, OnDestroy {
ngOnInit() {
this.clipboardService.links.subscribe(e => {
// if (this.loading) {
// this._snackBar.open(e + ' was not processed, the app is beasy parsing another thread', null, {
// duration: 5000
// });
// return;
// }
// this.processUrl(e);
this.ngZone.run(() => {
if (this.appService.isScanOpen) {
this._snackBar.open(e + ' was not processed, the app is busy parsing another thread', null, {
duration: 5000
});
return;
}
this.appService.scan(e);
});
});
}
@@ -30,8 +30,6 @@ export class MultiPostComponent implements OnInit, OnDestroy {
loading = true;
constructor(
// public dialogRef: MatDialogRef<MultiPostComponent>,
// @Inject(MAT_DIALOG_DATA) public data: { threadId: string; threadUrl: string },
private ngZone: NgZone,
private _snackBar: MatSnackBar,
private wsConnectionService: WsConnectionService,
@@ -39,7 +37,6 @@ export class MultiPostComponent implements OnInit, OnDestroy {
private serverService: ServerService
) {
this.websocketHandlerPromise = this.wsConnectionService.getConnection();
// this.threadId = data.threadId;
}
ngOnInit(): void {
@@ -137,12 +134,6 @@ export class MultiPostComponent implements OnInit, OnDestroy {
});
}
// close() {
// this.ngZone.run(() => {
// this.dialogRef.close();
// });
// }
submit() {
const data = (<VRPostParse[]>this.gridOptions.api.getSelectedRows()).map(e => ({
postId: e.postId,
@@ -1,35 +1,27 @@
<div class="container" style="height: 100%; background-color: snow">
<div class="container" style="height: 100%; background-color: white">
<div
[ngClass]="{
error: postDetails.status === 'ERROR',
stopped: postDetails.status === 'STOPPED',
pending: postDetails.status === 'PENDING'
}"
class="progress-bar-back"
style="position: relative; height: 100%;"
>
<div
[ngClass]="{
complete: postDetails.status === 'COMPLETE',
downloading: postDetails.status === 'DOWNLOADING'
}"
[style.width]="trunc(postDetails.progress) + '%'"
class="progress-bar"
style="position: absolute; height: 100%; width: 100%"
></div>
<div
class="progress-foreground"
fxLayout="row"
fxLayoutAlign="space-between"
style="position: absolute; background-color: transparent; width: 100%; height: 100%; padding: 0 8px;"
style="background-color: transparent; width: 100%; height: 100%;"
>
<span
><a (click)="goTo()" href="javascript:void(0)" style="color: rgba(0, 0, 0, 0.87);">{{
postDetails.url
}}</a></span
>
<span class="progress-percentage">{{ trunc(postDetails.progress) + '%' }}</span>
<div class="progress-bar" style="position: absolute; width: 100%; top: 37px; padding: 0 20px">
<mat-progress-bar [value]="postDetails.progress" class="example-margin" color="primary" mode="determinate">
</mat-progress-bar>
</div>
<span fxLayout="row">
<span style="padding-left: 20px"
><a (click)="goTo()" href="javascript:void(0)" style="color: rgba(0, 0, 0, 0.87);">{{
postDetails.url
}}</a></span
>
<span class="filler" fxFlex="grow"></span>
</span>
<span class="progress-percentage" style="padding-right: 20px">{{ trunc(postDetails.progress) + '%' }}</span>
</div>
</div>
</div>
@@ -1,21 +0,0 @@
.progress-bar-back {
transition: background-color 0.5s;
}
.progress-bar {
transition: width 0.5s, background-color 0.5s;
}
.complete {
background-color: #3865a3;
}
.pending {
background-color: white;
}
.error {
background-color: #eb6060;
}
.downloading {
background-color: #87a2c7;
}
.stopped {
background-color: grey;
}
@@ -0,0 +1,13 @@
@import '~@angular/material/theming';
@mixin post-detail-renderer-component-theme($theme) {
$blue: mat-palette($mat-blue);
.progress-bar .mat-progress-bar-fill::after {
background-color: mat-color($blue, 300);
}
.progress-bar .mat-progress-bar-buffer {
background-color: mat-color($blue, 100);
}
}
@@ -8,7 +8,7 @@ import { ICellRendererParams } from 'ag-grid-community';
import { ElectronService } from 'ngx-electron';
@Component({
selector: 'app-progress-cell',
selector: 'app-details-cell',
templateUrl: 'post-details-progress.component.html',
styleUrls: ['post-details-progress.component.scss']
})
@@ -1,7 +1,9 @@
<div class="container" style="height: 100%; background-color: snow">
<div class="container" style="height: 100%; background-color: white">
<div
[ngClass]="{
'pending-back': postState.status === 'PENDING'
'error-back': postState.status === 'ERROR',
'downloading-back': postState.status === 'DOWNLOADING' || postState.status === 'PARTIAL',
'complete-back': postState.status === 'COMPLETE'
}"
class="progress-bar-back"
style="position: relative; height: 100%; max-height: 48px;"
@@ -10,9 +12,9 @@
class="progress-foreground"
fxLayout="row"
fxLayoutAlign="space-between"
style="position: absolute; background-color: transparent; width: 100%; height: 100%;"
style="background-color: transparent; width: 100%; height: 100%;"
>
<div class="progress-bar" style="position: absolute; width: 100%; top: 37px; padding: 0 50px">
<div class="progress-bar" color="accent" style="position: absolute; width: 100%; top: 37px; padding: 0 50px">
<mat-progress-bar [value]="postState.progress" class="example-margin" color="primary" mode="determinate">
</mat-progress-bar>
</div>
@@ -1,9 +1,6 @@
.progress-bar-back {
transition: background-color 0.5s;
}
.pending-back {
background-color: snow;
}
.table {
display: table;
@@ -0,0 +1,45 @@
@import '~@angular/material/theming';
@mixin post-progress-renderer-component-theme($theme) {
$red: mat-palette($mat-red);
$grey: mat-palette($mat-grey);
$green: mat-palette($mat-green);
app-progress-cell .progress-bar .mat-progress-bar-fill::after {
background-color: mat-color($grey, 300);
}
app-progress-cell .progress-bar .mat-progress-bar-buffer {
background-color: mat-color($grey, 100);
}
app-progress-cell .error-back {
background-color: mat-color($red, 50);
& .progress-bar .mat-progress-bar-fill::after {
background-color: mat-color($red, 300);
}
& .progress-bar .mat-progress-bar-buffer {
background-color: mat-color($red, 100);
}
}
app-progress-cell .downloading-back {
background-color: mat-color($green, 50);
& .progress-bar .mat-progress-bar-fill::after {
background-color: mat-color($green, 300);
}
& .progress-bar .mat-progress-bar-buffer {
background-color: mat-color($green, 100);
}
}
app-progress-cell .complete-back {
background-color: mat-color($green, 100);
& .progress-bar .mat-progress-bar-fill::after {
background-color: mat-color($green, 300);
}
& .progress-bar .mat-progress-bar-buffer {
background-color: mat-color($green, 100);
}
}
}
+3 -3
View File
@@ -3,7 +3,7 @@
<h2 class="no-wrap" mat-dialog-title>Scan</h2>
</div>
<mat-dialog-content fxFlex="grow" fxLayout="column">
<div *ngIf="threadId == null">
<div *ngIf="!hideScan">
<form
#f="ngForm"
(ngSubmit)="submit(f)"
@@ -31,8 +31,8 @@
</ng-container>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-dialog-close mat-raised-button>Close</button>
<button (click)="addPosts()" *ngIf="multipost != null" color="primary" mat-raised-button type="submit">
<button (click)="close()" mat-raised-button>Close</button>
<button (click)="addPosts()" *ngIf="threadId != null" color="primary" mat-raised-button type="submit">
Download
</button>
</mat-dialog-actions>
+68 -42
View File
@@ -1,6 +1,6 @@
import { Component, OnInit, NgZone, ViewChild } from '@angular/core';
import { Component, OnInit, NgZone, ViewChild, Inject } from '@angular/core';
import { NgForm } from '@angular/forms';
import { MatSnackBar, MatDialog, MatDialogRef } from '@angular/material';
import { MatSnackBar, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { HttpClient } from '@angular/common/http';
import { finalize } from 'rxjs/operators';
import { ServerService } from '../server-service';
@@ -12,75 +12,101 @@ import { MultiPostComponent } from '../multi-post/multi-post.component';
styleUrls: ['./scan.component.scss']
})
export class ScanComponent implements OnInit {
constructor(
private ngZone: NgZone,
private httpClient: HttpClient,
private serverService: ServerService,
private _snackBar: MatSnackBar,
public dialogRef: MatDialogRef<ScanComponent>,
) { }
@Inject(MAT_DIALOG_DATA) public data: DialogData
) {}
@ViewChild(MultiPostComponent)
multipost: MultiPostComponent;
input: string;
threadId: string;
hideScan = false;
submit(form: NgForm) {
this.threadId = null;
this.processUrl(this.input, form);
this.ngZone.run(() => {
this.hideScan = true;
this.threadId = null;
this.processUrl(this.input, form);
});
}
done(done: boolean) {
if(done) {
this.dialogRef.close();
}
this.ngZone.run(() => {
if (done) {
this.dialogRef.close();
}
});
}
processUrl(url: string, form?: NgForm) {
this.ngZone.run(() => {
// this.loading = true;
});
this.httpClient
.post<{ threadId: string, postId: string}>(this.serverService.baseUrl + '/post', { url: url })
.pipe(finalize(() => {
this.ngZone.run(() => {
// this.loading = false;
});
if (form != null) {
form.resetForm();
this.input = null;
}
}))
.subscribe(response => {
if (response.postId != null) {
this.httpClient.post(this.serverService.baseUrl + '/post/add', [response]).subscribe(
() => {
this._snackBar.open('Adding posts to queue', null, {
duration: 5000
});
},
error => {
this._snackBar.open(error.error, null, {
duration: 5000
});
.post<{ threadId: string; postId: string }>(this.serverService.baseUrl + '/post', { url: url })
.pipe(
finalize(() => {
this.ngZone.run(() => {
if (form != null) {
form.resetForm();
this.input = null;
}
);
return;
}
this.threadId = response.threadId;
});
})
)
.subscribe(response => {
this.ngZone.run(() => {
if (response.postId != null) {
this.httpClient
.post(this.serverService.baseUrl + '/post/add', [response])
.pipe(finalize(() => this.dialogRef.close()))
.subscribe(
() => {
this._snackBar.open('Adding posts to queue', null, {
duration: 5000
});
},
error => {
this._snackBar.open(error.error, null, {
duration: 5000
});
}
);
return;
}
this.threadId = response.threadId;
});
});
}
addPosts() {
if (this.multipost != null) {
this.multipost.submit();
}
this.dialogRef.close();
this.ngZone.run(() => {
if (this.multipost != null) {
this.multipost.submit();
}
this.dialogRef.close();
});
}
ngOnInit() {
this.ngZone.run(() => {
if (this.data.url != null) {
this.hideScan = true;
this.processUrl(this.data.url);
}
});
}
close() {
this.ngZone.run(() => {
this.dialogRef.close();
});
}
}
export interface DialogData {
url: string;
}
@@ -1,21 +1,11 @@
@import '~@angular/material/theming';
// mixin name will be used in main style.scss
@mixin status-bar-component-theme($theme) {
// retrieve variables from theme
// (all possible variables, use only what you really need)
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, accent);
$foreground: map-get($theme, foreground);
$background: map-get($theme, background);
// all of these variables contain many additional variables
.status-bar {
background-color: mat-color($background, status-bar);
color: mat-color($foreground, base);
}
}
$foreground: map-get($theme, foreground);
$background: map-get($theme, background);
.status-bar {
background-color: mat-color($background, status-bar);
color: mat-color($foreground, base);
}
}
+1 -5
View File
@@ -9,11 +9,7 @@
$foreground: map-get($theme, foreground);
$background: map-get($theme, background);
.ag-row {
// transition: height,transform 0.5s;
}
.ag-header, .ag-icon {
.ag-header, .ag-header .ag-icon {
color: mat-color($foreground, secondary-text) !important;
}
+4
View File
@@ -3,11 +3,15 @@
@import 'mat-theme.scss';
@import 'app/status-bar/status-bar.component.scss.theme.scss';
@import 'app/app.component.scss-theme.scss';
@import 'app/posts/post-progress.renderer.component.scss-theme.scss';
@import 'app/post-detail/post-details-progress.component.scss-theme.scss';
@import 'grid-theme.scss';
@mixin custom-components-theme($theme) {
@include status-bar-component-theme($theme);
@include app-component-theme($theme);
@include post-progress-renderer-component-theme($theme);
@include post-detail-renderer-component-theme($theme);
}
.dark-theme {