Customise window decorations, add openfolder action to menu, fix toolbar colours

This commit is contained in:
Michael Pivato
2024-06-08 16:30:05 +09:30
parent 8808b00f4d
commit ecdd4f7080
11 changed files with 253 additions and 167 deletions

View File

@@ -1,11 +1,26 @@
<mat-toolbar><span>BufPiv</span></mat-toolbar>
<mat-toolbar data-tauri-drag-region color="secondary"
><h1>BufPiv</h1></mat-toolbar
>
<mat-sidenav-container autosize>
@if(selectedDirectory()) {
<mat-sidenav mode="side" opened>
<app-file-tree [files]="files()"></app-file-tree>
</mat-sidenav>
}
<mat-sidenav-content>
@if (!selectedDirectory) {
<button mat-button (click)="selectDirectory()">Open Folder</button>
@if (!selectedDirectory()) {
<div
style="
display: flex;
justify-content: center;
align-items: center;
height: 100%;
"
>
<button mat-button (click)="selectDirectory()" style="margin: auto">
Open Folder
</button>
</div>
}@else { }
</mat-sidenav-content>
<!-- TODO: Proto selector (add/remove proto definitinos, select definition for current file) on right side -->

View File

@@ -3,6 +3,12 @@
flex-direction: column;
height: 100%;
}
mat-toolbar {
flex: 0 0 auto;
padding-top: 24px;
--mat-toolbar-standard-height: 70px;
}
mat-sidenav-container {
width: 100%;
height: 100%;

View File

@@ -1,5 +1,11 @@
import { CommonModule } from '@angular/common';
import { Component, signal } from '@angular/core';
import {
ChangeDetectorRef,
Component,
OnDestroy,
OnInit,
signal,
} from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatSidenavModule } from '@angular/material/sidenav';
import { RouterOutlet } from '@angular/router';
@@ -12,6 +18,8 @@ import {
FileTreeComponent,
} from './file-tree/file-tree.component';
import { MatIconModule } from '@angular/material/icon';
import { listen, UnlistenFn } from '@tauri-apps/api/event';
import { OpenFolderMessage } from './messages/openfolder.message';
@Component({
selector: 'app-root',
@@ -30,9 +38,26 @@ import { MatIconModule } from '@angular/material/icon';
],
})
export class AppComponent {
protected selectedDirectory: string | null = null;
protected selectedDirectory = signal<string | null>(null);
protected files = signal<FileOrFolder[]>([]);
private unlisten?: UnlistenFn;
async ngOnInit() {
this.unlisten = await listen(
'openfolder',
async (event: OpenFolderMessage) => {
await this.selectDirectory();
}
);
}
async ngOnDestroy() {
if (this.unlisten) {
this.unlisten();
}
}
async selectDirectory() {
const selectedDirectory = await open({
directory: true,
@@ -40,22 +65,58 @@ export class AppComponent {
});
if (Array.isArray(selectedDirectory)) {
message('Only a single folder can be selected at a time');
return;
} else {
this.selectedDirectory = selectedDirectory;
this.selectedDirectory.set(selectedDirectory);
}
if (this.selectedDirectory) {
const entries = await readDir(this.selectedDirectory, {
if (selectedDirectory) {
const entries = await readDir(selectedDirectory, {
recursive: true,
});
this.files.set(entries.map((entry) => this.mapEntry(entry)));
const splitNumbers = /(\d)+|(\D)+/;
this.files.set(
entries
.sort(this.sortFiles(splitNumbers))
.map((entry) => this.mapEntry(entry, splitNumbers))
);
}
}
private mapEntry(entry: FileEntry): FileOrFolder {
private mapEntry(entry: FileEntry, splitNumbers: RegExp): FileOrFolder {
return {
isDirectory: entry.children != null,
name: entry.name || '',
children: entry.children?.map((entry) => this.mapEntry(entry)),
children: entry.children?.map((entry) =>
this.mapEntry(entry, splitNumbers)
),
};
}
private sortFiles =
(splitNumbers: RegExp) => (a: FileEntry, b: FileEntry) => {
return a.name?.localeCompare(b.name ?? '') ?? 0;
// if (!a.name) {
// return -1;
// }
// if (!b.name) {
// return 1;
// }
// const aSplit = splitNumbers.exec(a.name);
// const bSplit = splitNumbers.exec(b.name);
// if (!aSplit) {
// return -1;
// }
// if (!bSplit) {
// return 1;
// }
// for (
// let i = 0;
// i < (aSplit.length > bSplit.length ? bSplit.length : aSplit.length);
// i++
// ) {}
// // TODO: Alternative is to iterate through characters in the strings to find numbers, if there isn't a number then return
// // locale compare?
// // TODO: finish this
// return 0;
};
}

View File

@@ -40,7 +40,7 @@ interface FileNode {
<button mat-icon-button disabled></button>
{{ node.file.name }}
</mat-tree-node>
<mat-tree-node *matTreeNodeDef="let node; when: hasChild">
<mat-tree-node *matTreeNodeDef="let node; when: hasChild" matTreeNodeToggle>
<button
mat-icon-button
matTreeNodePadding
@@ -51,7 +51,7 @@ interface FileNode {
chevron_right }
</mat-icon>
</button>
{{ node.name }}
{{ node.file.name }}
</mat-tree-node>
</mat-tree>`,
styleUrl: './file-tree.component.scss',

View File

@@ -0,0 +1 @@
export interface OpenFolderMessage {}

View File

@@ -1,141 +0,0 @@
// This file was generated by running 'ng generate @angular/material:m3-theme'.
// Proceed with caution if making changes to this file.
@use 'sass:map';
@use '@angular/material' as mat;
// Note: Color palettes are generated from primary: #DF6B85, secondary: #AE868D, tertiary: #B48858, neutral: #988E8F
$_palettes: (
primary: (
0: #000000,
10: #3f0015,
20: #630828,
25: #721633,
30: #82233e,
35: #912f49,
40: #a13a54,
50: #c0536c,
60: #e06c86,
70: #ff86a0,
80: #ffb2bf,
90: #ffd9de,
95: #ffecee,
98: #fff8f7,
99: #fffbff,
100: #ffffff,
),
secondary: (
0: #000000,
10: #3f0017,
20: #5f112b,
25: #6d1d35,
30: #7c2940,
35: #8b344c,
40: #9a4058,
50: #b95870,
60: #d87189,
70: #f78aa3,
80: #ffb1c0,
90: #ffd9df,
95: #ffecee,
98: #fff8f7,
99: #fffbff,
100: #ffffff,
),
tertiary: (
0: #000000,
10: #2b1700,
20: #482900,
25: #573300,
30: #673d00,
35: #774700,
40: #885200,
50: #aa6800,
60: #c98121,
70: #e89b3a,
80: #ffb868,
90: #ffddbb,
95: #ffeedf,
98: #fff8f4,
99: #fffbff,
100: #ffffff,
),
neutral: (
0: #000000,
10: #3f0018,
20: #5f112c,
25: #6d1d37,
30: #7c2942,
35: #8b344e,
40: #9a4059,
50: #b85872,
60: #d7718b,
70: #f78aa5,
80: #ffb1c2,
90: #ffd9e0,
95: #ffecee,
98: #fff8f7,
99: #fffbff,
100: #ffffff,
),
neutral-variant: (
0: #000000,
10: #24191a,
20: #3a2d2f,
25: #46383a,
30: #524345,
35: #5e4f51,
40: #6a5a5c,
50: #847375,
60: #9f8c8e,
70: #baa6a9,
80: #d6c2c4,
90: #f3dddf,
95: #ffecee,
98: #fff8f7,
99: #fffbff,
100: #ffffff,
),
error: (
0: #000000,
10: #410002,
20: #690005,
25: #7e0007,
30: #93000a,
35: #a80710,
40: #ba1a1a,
50: #de3730,
60: #ff5449,
70: #ff897d,
80: #ffb4ab,
90: #ffdad6,
95: #ffedea,
98: #fff8f7,
99: #fffbff,
100: #ffffff,
),
);
$_rest: (
secondary: map.get($_palettes, secondary),
neutral: map.get($_palettes, neutral),
neutral-variant: map.get($_palettes, neutral-variant),
error: map.get($_palettes, error),
);
$_primary: map.merge(map.get($_palettes, primary), $_rest);
$_tertiary: map.merge(map.get($_palettes, tertiary), $_rest);
$light-theme: mat.define-theme((
color: (
theme-type: light,
primary: $_primary,
tertiary: $_tertiary,
),
));
$dark-theme: mat.define-theme((
color: (
theme-type: dark,
primary: $_primary,
tertiary: $_tertiary,
),
));

View File

@@ -1,10 +1,17 @@
@use '@angular/material' as mat;
@use './m3-theme.scss';
@use "@angular/material" as mat;
@use "./theme.scss";
@include mat.core();
@mixin custom-colours($theme) {
.mat-toolbar {
background-color: mat.get-theme-color($theme, primary-container);
}
}
html {
@include mat.all-component-themes(m3-theme.$dark-theme);
@include mat.all-component-themes(theme.$rose-theme);
@include custom-colours(theme.$rose-theme);
}
html,

10
src/theme.scss Normal file
View File

@@ -0,0 +1,10 @@
@use "@angular/material" as mat;
$rose-theme: mat.define-theme(
(
color: (
theme-type: dark,
primary: mat.$rose-palette,
),
)
);