Skip to content

Commit

Permalink
Merge pull request #133 from invince/develop
Browse files Browse the repository at this point in the history
Release 1.0.0
  • Loading branch information
invince authored Jan 12, 2025
2 parents c5af182 + 3679a58 commit 0ca0b73
Show file tree
Hide file tree
Showing 29 changed files with 149 additions and 65 deletions.
2 changes: 2 additions & 0 deletions TestPlan.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
- download ok

# Terminal
- reconnect: open a ssh terminal, reboot, then the reconnect button should appear
- after you click it, your session should be reconnected

## Local Terminal
- (Settings) if default open option checked, then a local terminal should start at startup
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yet-another-electron-term",
"version": "1.0.1",
"version": "1.0.0",
"main": "src-electron/electronMain.js",
"scripts": {
"ng": "ng",
Expand All @@ -13,15 +13,15 @@
"electron:dev": "wait-on http://localhost:4200 && cross-env NODE_ENV=development electron .",
"postinstall": "patch-package",
"build:release": "npm run clean && patch-package && ng build --base-href ./ && electron-builder --publish always",
"release": "npm run build:release && npm version patch"
"release": "npm version patch && npm run build:release"
},
"build": {
"appId": "io.github.invince",
"productName": "YetAnotherElectronTerm",
"publish": {
"provider": "github",
"owner": "invince",
"repo": "YAET"
"repo": "YAET-RELEASE"
},
"nsis": {
"oneClick": false,
Expand Down
3 changes: 3 additions & 0 deletions src-electron/ipc/terminal.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,15 @@ function initTerminalIpcHandler(log, terminalMap) {
// Handle end event
conn.on('end', () => {
log.info('SSH connection ended for id:', id);

});

// Handle close event
conn.on('close', (hadError) => {
if (hadError) {
log.info(`SSH connection closed for id: ${id}, hadError: ${hadError}`);
event.sender.send('session.disconnect.terminal.ssh', { id: id , error: hadError });
} else {
event.sender.send('session.disconnect.terminal.ssh', { id: id });
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</mat-sidenav>

<mat-sidenav-content>
<mat-tab-group id="tab-group" [@.disabled]="true" [selectedIndex]="tabService.currentTabIndex">
<mat-tab-group id="tab-group" [@.disabled]="true" [(selectedIndex)]="tabService.currentTabIndex">
@for (tab of tabService.tabs ; let i = $index; track tab.id) {
<mat-tab>
<ng-template mat-tab-label>
Expand Down
17 changes: 10 additions & 7 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ export class AppComponent implements OnInit, OnDestroy{
}
this.modalControl.closeModal([this.MENU_PROFILE, this.MENU_ADD ]);
if (Profile.requireOpenNewTab(profile)) {
this.tabService.addTab(new TabInstance(profile.category, this.sessionService.create(profile, profile.profileType))); // Adds a new terminal identifier
this.tabService.currentTabIndex = this.tabService.tabs.length - 1;
const tab = new TabInstance(profile.category, this.sessionService.create(profile, profile.profileType));
this.tabService.addTab(tab); // Adds a new terminal identifier
this.tabService.currentTabIndex = this.tabService.tabs.findIndex(one => one.id === tab.id);
} else {
this.sessionService.openSessionWithoutTab(profile);
}
Expand Down Expand Up @@ -145,7 +146,8 @@ export class AppComponent implements OnInit, OnDestroy{
}

removeTab(index: number) {
this.tabService.tabs.splice(index, 1);
this.tabService.removeTab(index);

}


Expand All @@ -154,14 +156,15 @@ export class AppComponent implements OnInit, OnDestroy{
}

reconnect(i: number) {
this.tabService.reconnect(i);
this.sessionService.reconnect(i);
}

addLocalTerminal() {
this.modalControl.closeModal();
this.tabService.addTab(new TabInstance( ProfileCategory.TERMINAL,
this.sessionService.create(this.settingService.createLocalTerminalProfile(),ProfileType.LOCAL_TERMINAL))); // Adds a new terminal identifier
this.tabService.currentTabIndex = this.tabService.tabs.length - 1;
const tab = new TabInstance( ProfileCategory.TERMINAL,
this.sessionService.create(this.settingService.createLocalTerminalProfile(),ProfileType.LOCAL_TERMINAL));
this.tabService.addTab(tab); // Adds a new terminal identifier
this.tabService.currentTabIndex = this.tabService.tabs.findIndex(one => one.id === tab.id);
}


Expand Down
2 changes: 1 addition & 1 deletion src/app/components/menu/cloud/cloud.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export class CloudComponent extends MenuComponent implements OnInit, OnDestroy {
}

filterSecret() {
return this.secretStorageService.data.secrets?.filter(one => one.secretType == SecretType.LOGIN_PASSWORD);
return this.secretStorageService.filter(one => one.secretType == SecretType.LOGIN_PASSWORD);
}

quickCreateSecret() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,15 @@
<mat-form-field class="field" required>
<mat-label>Secret</mat-label>
<mat-select (selectionChange)="onSelectSecret($event)" formControlName="secretId">
@for (oneSecret of secretStorageService.data.secrets; track oneSecret.id) {
<mat-option (click)="quickCreateSecret()">
<mat-icon>add</mat-icon>
Add New...
</mat-option>
@for (oneSecret of filterSecret(); track oneSecret.id) {
<mat-option [value]="oneSecret.id">
@if (oneSecret.icon) {
<mat-icon>{{oneSecret.icon}}</mat-icon>
}
{{ secretService.displaySecretOptionName(oneSecret) }}
</mat-option>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {Component, forwardRef, Injector, Self} from '@angular/core';
import {Component, forwardRef, Injector} from '@angular/core';
import {CommonModule} from '@angular/common';
import {
FormBuilder,
FormGroup,
FormsModule, NG_VALIDATORS,
FormsModule,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
Validators
Expand All @@ -16,7 +17,7 @@ import {MatIcon} from '@angular/material/icon';
import {MatIconButton} from '@angular/material/button';
import {ChildFormAsFormControl} from '../../../enhanced-form-mixin';
import {MenuComponent} from '../../menu.component';
import {AuthType} from '../../../../domain/Secret';
import {AuthType, SecretType} from '../../../../domain/Secret';
import {SecretStorageService} from '../../../../services/secret-storage.service';
import {SecretService} from '../../../../services/secret.service';
import {SettingStorageService} from '../../../../services/setting-storage.service';
Expand All @@ -27,6 +28,8 @@ import {
ModelFieldWithPrecondition,
ModelFormController
} from '../../../../utils/ModelFormController';
import {SecretQuickFormComponent} from '../../../dialog/secret-quick-form/secret-quick-form.component';
import {MatDialog} from '@angular/material/dialog';

@Component({
selector: 'app-custom-profile-form',
Expand Down Expand Up @@ -72,6 +75,7 @@ export class CustomProfileFormComponent extends ChildFormAsFormControl(MenuCompo
public secretStorageService: SecretStorageService, // in html
public secretService: SecretService, // in html
public settingStorage: SettingStorageService,
public dialog: MatDialog,
) {
super();

Expand Down Expand Up @@ -150,4 +154,17 @@ export class CustomProfileFormComponent extends ChildFormAsFormControl(MenuCompo
this.form.get('secretId')?.setValue(null);
}
}

quickCreateSecret() {
this.dialog.open(SecretQuickFormComponent, {
width: '650px',
data: {
secretTypes: [SecretType.LOGIN_PASSWORD, SecretType.PASSWORD_ONLY]
}
});
}

filterSecret() {
return this.secretStorageService.filter(one => one.secretType == SecretType.LOGIN_PASSWORD || one.secretType == SecretType.PASSWORD_ONLY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
<mat-icon>add</mat-icon>
Add New...
</mat-option>
@for (oneSecret of secretStorageService.data.secrets; track oneSecret.id) {
@for (oneSecret of secretStorageService.dataCopy.secrets; track oneSecret.id) {
<mat-option [value]="oneSecret.id">
@if (oneSecret.icon) {
<mat-icon>{{oneSecret.icon}}</mat-icon>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export class VncProfileFormComponent extends ChildFormAsFormControl(MenuComponen
}

filterSecret() {
return this.secretStorageService.data.secrets?.filter(one => one.secretType == SecretType.PASSWORD_ONLY);
return this.secretStorageService.filter(one => one.secretType == SecretType.PASSWORD_ONLY);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h3>Profiles</h3>
<mat-nested-tree-node *matTreeNodeDef="let node" >
<div class="group-name"
[class.selected]="node.profile && node.profile.id === selectedProfileId"
(click)="onTabChange(node.profile)">
(click)="onTabChange(node.profile)" (dblclick)="onTabConnect(node.profile)">
@if (node.profile.icon) {
<mat-icon>{{node.profile.icon}}</mat-icon>
}
Expand Down Expand Up @@ -78,12 +78,12 @@ <h3>Profiles</h3>
</mat-nested-tree-node>
</mat-tree>
}
@else {
@else { // in list mode
@for (profile of profilesCopy.profiles | filterKeyword:keywordsProviders:filter; track profile.id) {
<div class="sidenav-item">
<button mat-button
[class.selected]="profile.id === selectedProfileId"
(click)="onTabChange(profile)">
(click)="onTabChange(profile)" (dblclick)="onTabConnect(profile)">
@if (profile.icon) {
<mat-icon>{{profile.icon}}</mat-icon>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export class ProfilesMenuComponent extends HasChildForm(MenuComponent) implement
this.notification.info(message);
}

this.profilesCopy = this.profileService.profiles;
this.profilesCopy = this.profileService.profilesCopy;
this.profilesCopy.profiles = this.profilesCopy.profiles.sort((a: Profile, b: Profile) => a.name.localeCompare(b.name));
this.sideNavType = this.settingStorage.settings.ui.profileSideNavType;
this.refreshForm();
Expand Down Expand Up @@ -134,6 +134,10 @@ export class ProfilesMenuComponent extends HasChildForm(MenuComponent) implement
this.doAddTabOfProfile(Profile.clone($event));
}

onTabConnect(profile: Profile) {
this.profileService.onProfileConnect(profile);
}

onTabChange(profile: Profile) {
if (!profile) {
return;
Expand Down Expand Up @@ -297,4 +301,6 @@ export class ProfilesMenuComponent extends HasChildForm(MenuComponent) implement
async commitChange() {
await this.profileService.save(this.profilesCopy);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class QuickconnectMenuComponent extends MenuComponent implements OnInit
}

ngOnInit(): void {
this.profilesCopy = this.profileService.profiles;
this.profilesCopy = this.profileService.profilesCopy;
}

async onSaveOne($event: Profile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class SecretFormMixin {
static secretNameShouldBeUnique(secretStorageService: SecretStorageService, secret: Secret | undefined = undefined) { // NOTE: inside validatorFn, we cannot use inject thing
return (group: FormGroup) => {
let name = group.get("name")?.value;
if (name && secretStorageService.data.secrets?.find(one => one.name === name && one.id !== secret?.id)) {
if (name && secretStorageService.dataCopy.secrets?.find(one => one.name === name && one.id !== secret?.id)) {
return {duplicateSecret: true};
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export class SecretsMenuComponent extends HasChildForm(MenuComponent) implements
this.secretService.reload();
}

this.secretsCopy = this.secretStorageService.data;
this.secretsCopy = this.secretStorageService.dataCopy;
this.secretsCopy.secrets = this.secretsCopy.secrets.sort((a: Secret, b: Secret) => a.name.localeCompare(b.name));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class GroupsFormComponent implements OnInit{
createGroupDataSource(): GroupNode[] {
return GroupNode.map2DataSource(
this.settingStorage.settings.groups,
this.profileService.profiles.profiles,
this.profileService.profilesCopy.profiles,
true,
false,
(group, node) => {
Expand Down
14 changes: 12 additions & 2 deletions src/app/components/menu/setting-menu/setting-menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import {SecretType} from '../../../domain/Secret';
import {SecretStorageService} from '../../../services/secret-storage.service';
import {SecretService} from '../../../services/secret.service';



@Component({
selector: 'app-setting-menu',
standalone: true,
Expand Down Expand Up @@ -75,7 +77,7 @@ export class SettingMenuComponent extends MenuComponent implements OnInit, OnDes
remoteDesktopForm!: FormGroup;
fileExplorerForm!: FormGroup;

LOCAL_TERM_OPTIONS = LocalTerminalType;
LOCAL_TERM_OPTIONS: LocalTerminalType[] = this.getLocalTermOptions();

SIDE_NAV_TYPE_OPTIONS = SideNavType;

Expand Down Expand Up @@ -367,7 +369,15 @@ export class SettingMenuComponent extends MenuComponent implements OnInit, OnDes
}

filterSecret() {
return this.secretStorageService.data.secrets?.filter(one => one.secretType == SecretType.LOGIN_PASSWORD);
return this.secretStorageService.filter(one => one.secretType == SecretType.LOGIN_PASSWORD);
}

getLocalTermOptions(): LocalTerminalType[] {
if (process.platform === 'win32') {
return [ LocalTerminalType.CMD , LocalTerminalType.POWERSHELL, LocalTerminalType.BASH];
} else {
return [LocalTerminalType.BASH];
}
}

}
4 changes: 3 additions & 1 deletion src/app/components/terminal/terminal.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<div class="terminal-container" #termContainer>
<div class="terminal">
<ng-terminal #term></ng-terminal>
<ng-terminal
[cols]="150"
#term></ng-terminal>
</div>
<div class="terminal-footer">
&nbsp;
Expand Down
Loading

0 comments on commit 0ca0b73

Please sign in to comment.