Skip to content

Commit c1a435e

Browse files
authored
Misc fixes (#185)
* hacky fix for issue with torrent contents not displaying - update README with better setup instructions * view more info for torrent by right-clicking the table row * update README
1 parent d7c6ac9 commit c1a435e

File tree

6 files changed

+41
-34
lines changed

6 files changed

+41
-34
lines changed

README.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,26 @@
44

55
A material-themed UI for [qBittorrent](https://github.com/qbittorrent/qBittorrent). This interface is more slimmed down, although still contains several features such as:
66

7+
* See torrent contents _before_ downloading
8+
* File system navigation (choose where to save a torrents, create sub-folders, etc.)
79
* Bulk edit (pause, resume, delete, prioritize, and more)
810
* Sorting by different metrics (name, size, date completed, etc.)
9-
* See torrent contents _before_ downloading
10-
* File system navigation (choose where to save a torrent, create sub-folders, etc.)
1111
* Manage local & qBittorrent preferences
1212
* A fully material-themed UI (Light & Dark themes)
1313
* ... and more!
1414

1515
## Demo!
16-
A live demo is available here: https://qbit-material-webui-demo.herokuapp.com/.
16+
A live demo is available here: https://qbit-material-webui-demo.herokuapp.com/
1717

1818

1919
## Installation
20-
This app is tested with **v4.1.5** and higher of qBittorrent, any lower version are not guaranteed to work.
20+
This app is tested with **v4.3.8** and higher of qBittorrent, any lower version are not guaranteed to work.
21+
22+
### Automatic -- Docker Mods Support!
23+
Thanks to @marzzzello for adding support in LinuxServer.io's qBittorrent container: https://github.com/marzzzello/linuxserver-io-mod-qbit-matui
24+
2125

26+
### Manual
2227
1. Take a production-ready build from [releases](https://github.com/bill-ahmed/qbit-material-WebUI/releases), or [build it yourself](#build)
2328
2. Extract the files into any folder
2429
3. In qBittorrent, under Tools > Options > Web UI > Use alternative Web UI, set the file location as the folder you created in Step 2.
@@ -32,25 +37,22 @@ This app relies on a couple files to work properly.
3237
Under `src/assets/` there are two files: `config.json` and `config.prod.json`. This will store general configuration, such as the delimeter used when parsing file paths (Unix vs. Windows).
3338

3439
### HTTP Config
35-
If you wish to configure your endpoints and other data for dev/prod, do so here.
40+
If you wish to configure your endpoints and other data for dev/prod, do so in `src/assets/http_config.json`.
3641

3742

3843
## Running the App
39-
To install the dependencies, run `npm install` in both the root directory and the `mock_backend/` folder.
44+
In order to have the most accurate testing environment, we make use of a docker container running qBittorrent. Make
45+
sure you have both Docker and docker-compose installed.
4046

41-
### Back-end
42-
1. Navigate to `mock_backend` directory
43-
2. Run `node index.js`
47+
Checkout the instructions in the `dev/` folder on how to set it up.
4448

45-
### Front-end:
46-
1. Run `ng serve` for a dev server
47-
2. Navigate to `http://localhost:4200/`
48-
3. Username: `admin`; Password: `password`; This can be changed under `mock_backend/config.json`
49-
50-
To run the login page standalone, do: `ng serve login` and navigate to `http://localhost:4200/`.
5149

52-
The app will automatically reload if you make changes to any of the Angular source code.
50+
### Front-end:
51+
1. Run `npm run dev` for a dev server
52+
2. Navigate to `http://localhost:8090/`
53+
3. Username: `admin`; Password: `adminadmin`; This can be changed through the default Web UI.
5354

55+
The app will re-compile everytime you save changes. To see the changes, you must hard-reload the web page (`CTRL + SHIFT + R` on Windows)
5456

5557
## Build
5658

src/app/modals/add-torrent-dialog/add-torrent-dialog.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ <h2 mat-dialog-title>Upload Torrents</h2>
1313
<mat-dialog-content class="mat-typography dialog_content">
1414
<mat-tab-group mat-align-tabs="start" (selectedTabChange)="handleTabChange($event)" [selectedIndex]="currentTab?.index || 0">
1515
<mat-tab label="File Upload">
16-
<div class="file_upload_container">
16+
<div class="file_upload_container" style="padding-top: 25px;">
1717
<br/>
1818

1919
<div [ngClass]="{'dark-theme': isDarkTheme | async}" class="upload_files" appDragAndDropFiles (fileDropped)="updateFiles($event, true)" (click)="torrentFileUpload.click()">

src/app/modals/add-torrent-dialog/add-torrent-dialog.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { TorrentDataStoreService } from '../../services/torrent-management/torre
77
import { FileSystemDialogComponent } from '../file-system-dialog/file-system-dialog.component';
88
import { ThemeService } from '../../services/theme.service';
99
import { Observable } from 'rxjs';
10-
import { SerializedNode } from '../../services/file-system/file-system.service';
10+
import {FileSystemService, SerializedNode} from '../../services/file-system/file-system.service';
1111
import { GetDefaultSaveLocation, IsMobileUser } from 'src/utils/Helpers';
1212
import { MatTabChangeEvent } from '@angular/material/tabs';
1313
import { TorrentParserService } from 'src/app/services/torrent-management/torrent-parser.service';
@@ -45,6 +45,7 @@ export class AddTorrentDialogComponent implements OnInit {
4545

4646
constructor(private appConfig: ApplicationConfigService, private dialogRef:MatDialogRef<AddTorrentDialogComponent>, private data_store: TorrentDataStoreService,
4747
private torrentParser: TorrentParserService, public fileSystemDialog: MatDialog, public snackbar: SnackbarService, private theme: ThemeService,
48+
private fsService: FileSystemService,
4849
@Inject(MAT_DIALOG_DATA) inputData) { this.inputData = inputData }
4950

5051
ngOnInit(): void {
@@ -221,6 +222,8 @@ export class AddTorrentDialogComponent implements OnInit {
221222
this.fileSystemExplorerDialogREF.afterClosed().subscribe((res: string) => {
222223
// If use confirmed choice of file path
223224
if(res) {
225+
// Hack: Unix-based OS use '/', so we need it to be leading
226+
if (this.fsService.getFileSystemDelimeter() === '/') res = '/' + res
224227
this.filesDestination = res
225228
}
226229
})

src/app/services/file-system/FileSystemNodes/Inode.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@ export default class Inode extends TreeNode implements SerializableNode {
7373
return this.parent.getAbsolutePath(delimiter) + this.value + delimiter;
7474
}
7575

76-
// Hack: Unix-based OS use '/', so we need it to be leading
77-
if (delimiter === '/') return '/' + this.value
7876
return this.value
7977
}
8078

src/app/torrents-table/torrents-table.component.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
[contextMenu]="cm"
2828
[(contextMenuSelection)]="contextMenuSelectedTorrent"
2929

30-
[resizableColumns]="true"
30+
[resizableColumns]="true"
3131
columnResizeMode="expand"
3232
responsiveLayout="scroll"
3333

@@ -38,18 +38,18 @@
3838
<!-- TABLE HEADER -->
3939
<ng-template pTemplate="header">
4040
<tr>
41-
<th *ngFor="let col of displayedColumns"
42-
[id]="getIdForColumns(col)"
43-
[class]="getClassNameForColumns(col)"
44-
45-
pReorderableColumn
41+
<th *ngFor="let col of displayedColumns"
42+
[id]="getIdForColumns(col)"
43+
[class]="getClassNameForColumns(col)"
44+
45+
pReorderableColumn
4646

4747
pResizableColumn
48-
[pResizableColumnDisabled]="['select', 'Actions'].includes(col)"
48+
[pResizableColumnDisabled]="['select', 'Actions'].includes(col)"
4949

5050
[pSortableColumn]="displayedColumnsMapping[col]"
5151
>
52-
52+
5353
<div style="display: flex;" [ngSwitch]="col">
5454
<!-- Checkbox for selecting ALL torrents -->
5555
<div *ngSwitchCase="'select'">
@@ -79,7 +79,7 @@
7979
[ngClass]="{selected: isSelected(torrent)}"
8080

8181
(click)="handleTorrentSelected(torrent)"
82-
(contextmenu)="handleTorrentSelected(torrent)"
82+
(contextmenu)="torrentRightClicked = torrent"
8383

8484
[pContextMenuRow]="torrent"
8585
>
@@ -206,7 +206,7 @@
206206
</button>
207207
</div>
208208
</mat-card-header>
209-
209+
210210
<mat-card-content class="torrent-card-view-content">
211211
<!-- Show tags -->
212212
<mat-card-subtitle style="width: max-content;">
@@ -233,7 +233,7 @@
233233
<i class="pi pi-arrow-up"></i>&nbsp;: {{getFileSizeString(torrent.upspeed)}}/s
234234
</p>
235235
</div>
236-
236+
237237
<!-- Progress bar -->
238238
<div class="row">
239239
<p-progressBar class="custom_progress_bar {{torrent.progress > 0.5 ? 'white_label' : ''}}"

src/app/torrents-table/torrents-table.component.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,12 @@ export class TorrentsTableComponent implements OnInit {
6565
private torrentSearchValue = ""; // Keep track of which torrents are currently selected
6666
private torrentFilterBy: TorrentFilter = { type: '', value: '' };
6767

68+
// When user right-clicks a row in the torrent table, so we can choose what to do with it
69+
public torrentRightClicked: Torrent = null;
70+
6871
constructor(private appConfig: ApplicationConfigService, private data_store: TorrentDataStoreService,
6972
private pp: PrettyPrintTorrentDataService, public deleteTorrentDialog: MatDialog, private infoTorDialog: MatDialog, private moveTorrentDialog: MatDialog,
70-
private torrentSearchService: TorrentSearchServiceService, private filterService: TorrentFilterService, private torrentsSelectedService: RowSelectionService,
73+
private torrentSearchService: TorrentSearchServiceService, private filterService: TorrentFilterService, private torrentsSelectedService: RowSelectionService,
7174
private snackbar: SnackbarService, private theme: ThemeService) { }
7275

7376
ngOnInit(): void {
@@ -103,6 +106,7 @@ export class TorrentsTableComponent implements OnInit {
103106
});
104107

105108
this.contextMenuItems = [
109+
{ label: 'More Info', icon: 'pi pi-fw pi-info-circle', command: () => this.openInfoTorrentDialog(null, this.torrentRightClicked) },
106110
{ label: 'Pause', icon: 'pi pi-fw pi-pause', command: () => this.pauseTorrentsBulk(this.selection.selected) },
107111
{ label: 'Resume', icon: 'pi pi-fw pi-play', command: () => this.resumeTorrentsBulk(this.selection.selected) },
108112
{ label: 'Force Resume', icon: 'pi pi-fw pi-forward', command: () => this.forceStartTorrentsBulk(this.selection.selected) },
@@ -215,7 +219,7 @@ export class TorrentsTableComponent implements OnInit {
215219

216220
if(this.torrentFilterBy.type === 'filter_status')
217221
return Constants.TORRENT_STATE_MAPPING[this.torrentFilterBy.value]?.includes(tor.state);
218-
222+
219223
if(this.torrentFilterBy.type === 'filter_tracker')
220224
return this.allTorrentInformation.trackers[this.torrentFilterBy.value].includes(tor.hash)
221225
});
@@ -306,7 +310,7 @@ export class TorrentsTableComponent implements OnInit {
306310
this.colWidths = this.appConfig.getWebUISettings().torrent_table.column_widths;
307311
this.updateTorrentData(this.allTorrentInformation);
308312
}
309-
313+
310314
/** Determine whether a torrent is selected or not */
311315
isSelected(tor: Torrent): boolean {
312316
return this.selection.isSelected(tor);

0 commit comments

Comments
 (0)