finalized desktop version and first try implementing mobile

This commit is contained in:
Manuel 2024-05-28 14:41:41 +02:00
parent fe25daeaca
commit 7f944081a0
18 changed files with 395 additions and 27 deletions

View file

@ -12,6 +12,7 @@
"menu:default", "menu:default",
"tray:default", "tray:default",
"window:allow-set-title", "window:allow-set-title",
"dialog:allow-open" "dialog:allow-open",
"dialog:allow-message"
] ]
} }

View file

@ -0,0 +1,19 @@
{
"$schema": "../gen/schemas/mobile-schema.json",
"identifier": "mobile-capability",
"windows": ["main"],
"platforms": ["iOS", "android"],
"permissions": [
"path:default",
"event:default",
"window:default",
"app:default",
"resources:default",
"menu:default",
"tray:default",
"window:allow-set-title",
"dialog:allow-open",
"dialog:allow-message",
"menu:allow-get"
]
}

View file

@ -8,7 +8,7 @@ android {
compileSdk = 33 compileSdk = 33
namespace = "com.tauri.caesar_tauri_angular" namespace = "com.tauri.caesar_tauri_angular"
defaultConfig { defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false" manifestPlaceholders["usesCleartextTraffic"] = "true"
applicationId = "com.tauri.caesar_tauri_angular" applicationId = "com.tauri.caesar_tauri_angular"
minSdk = 24 minSdk = 24
targetSdk = 33 targetSdk = 33

View file

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application <application
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.caesar_tauri_angular" android:theme="@style/Theme.caesar_tauri_angular"
android:usesCleartextTraffic="${usesCleartextTraffic}"> android:usesCleartextTraffic="true"
android:requestLegacyExternalStorage="true">
<activity <activity
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
android:launchMode="singleTask" android:launchMode="singleTask"

View file

@ -8,6 +8,7 @@
"beforeBuildCommand": "npm run build", "beforeBuildCommand": "npm run build",
"frontendDist": "../dist/caesar-tauri-angular/browser" "frontendDist": "../dist/caesar-tauri-angular/browser"
}, },
"app": {"windows": [ "app": {"windows": [
{ {
"title": "caesar-tauri-angular", "title": "caesar-tauri-angular",
@ -16,7 +17,8 @@
} }
], ],
"security": { "security": {
"csp": null "csp": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;",
"capabilities": ["main-capability", "mobile-capability"]
} }
}, },
"bundle": { "bundle": {

View file

@ -1,19 +1,20 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Router, RouterOutlet } from '@angular/router'; import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
import { SenderComponent } from './components/sender/sender.component'; import { SenderComponent } from './components/sender/sender.component';
import { TauriService } from './services/tauri.service'; import { TauriService } from './services/tauri.service';
import { ReceiverComponent } from './components/receiver/receiver.component'; import { ReceiverComponent } from './components/receiver/receiver.component';
import { SettingsMenuComponent } from './components/settings-menu/settings-menu.component';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
standalone: true, standalone: true,
imports: [CommonModule, RouterOutlet, SenderComponent, ReceiverComponent], imports: [CommonModule, RouterOutlet, SenderComponent, ReceiverComponent, SettingsMenuComponent],
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrl: './app.component.css' styleUrl: './app.component.css'
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
constructor(private tauriService: TauriService, private router: Router) {} constructor(private tauriService: TauriService, private route: ActivatedRoute) {}
ngOnInit() { ngOnInit() {
console.log("Init") console.log("Init")
// this.tauriService.serve(8000, 'localhost').then(message => console.log(message)); // this.tauriService.serve(8000, 'localhost').then(message => console.log(message));

View file

@ -1,3 +1,5 @@
<app-settings-menu></app-settings-menu>
<div class="menu-container"> <div class="menu-container">
<nav class="menu"> <nav class="menu">
<ul> <ul>

View file

@ -1,10 +1,11 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { SettingsMenuComponent } from '../settings-menu/settings-menu.component';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
standalone: true, standalone: true,
imports: [], imports: [SettingsMenuComponent],
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrl: './home.component.css' styleUrl: './home.component.css'
}) })

View file

@ -1,23 +1,35 @@
<h2>Receiver</h2> <h2>Receiver</h2>
<p>Hier können Sie Dateien empfangen.</p> <p>Here you can receive Data</p>
<div class="form-group"> <div *ngIf="!isReceiving&& !receiveSuccess && !isRelayServerSet" class="form-group">
<label for="relayAddress">Relay Server Adresse:</label> <label for="relayAddress">Relay Server Adresse:</label>
<input type="text" id="relayAddress" [(ngModel)]="relayAddress" placeholder="::1"> <input type="text" id="relayAddress" [(ngModel)]="relayAddress" placeholder="::1">
</div> </div>
<div class="form-group"> <div *ngIf="!isReceiving&& !receiveSuccess && !isPortSet" class="form-group">
<label for="relayPort">Port:</label> <label for="relayPort">Port:</label>
<input type="text" id="relayPort" [(ngModel)]="relayPort" placeholder="8000"> <input type="text" id="relayPort" [(ngModel)]="relayPort" placeholder="8000">
</div> </div>
<div class="form-group"> <div *ngIf="!isReceiving" class="form-group">
<label for="relayPort">Transfername:</label> <label for="relayPort">Transfername:</label>
<input type="text" id="transferName" [(ngModel)]="transferName" placeholder="Transfername"> <input type="text" id="transferName" [(ngModel)]="transferName" placeholder="Transfername">
</div> </div>
<div class="form-group"> <div *ngIf="!isReceiving&& !receiveSuccess" class="form-group">
<button (click)="receiveData()">Daten empfangen</button> <button (click)="receiveData()">Daten empfangen</button>
</div> </div>
<div class="form-group"> <div *ngIf="!isReceiving&& !receiveSuccess" class="form-group">
<button (click)="redirectToHome()">Startseite</button> <button (click)="redirectToHome()">Startseite</button>
</div> </div>
<div>
<p *ngIf="isReceiving">Receiving Data... Transfer Name: {{transferName}}</p>
</div>
<div *ngIf="!isReceiving && receiveSuccess">
<p>Data received successfully! Transfer Name: {{transferName}}</p>
</div>
<div *ngIf="!isReceiving && !receiveSuccess && transferName === ''">
<p> No Data is being received. </p>
</div>

View file

@ -1,8 +1,9 @@
import { Component } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { TauriService } from '../../services/tauri.service'; import { TauriService } from '../../services/tauri.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { StorageService } from '../../services/storage.service';
@Component({ @Component({
selector: 'app-receiver', selector: 'app-receiver',
@ -11,22 +12,50 @@ import { CommonModule } from '@angular/common';
templateUrl: './receiver.component.html', templateUrl: './receiver.component.html',
styleUrl: './receiver.component.css' styleUrl: './receiver.component.css'
}) })
export class ReceiverComponent { export class ReceiverComponent implements OnInit {
relayAddress: string = ''; relayAddress: string = '';
relayPort?: number; relayPort?: number;
transferName: string = ''; transferName: string = '';
constructor(private tauriService: TauriService, private router: Router) {} isRelayServerSet = false;
isPortSet = false;
isReceiving = false;
receiveSuccess = false;
constructor(private tauriService: TauriService, private router: Router, private storage: StorageService) {}
ngOnInit(): void {
if(this.storage.getLocalEntry('relayServer')) {
this.isRelayServerSet = true;
this.relayAddress = this.storage.getLocalEntry('relayServer')
}
if(this.storage.getLocalEntry('port')) {
this.isPortSet = true;
this.relayPort = this.storage.getLocalEntry('port')
}
console.log("Moin")
}
redirectToHome() { redirectToHome() {
this.router.navigate(['']) this.router.navigate([''])
} }
reset() {
this.isReceiving = false;
this.receiveSuccess = false;
this.transferName = '';
}
getRelayURL(): string { getRelayURL(): string {
return `ws://${this.relayAddress}:${this.relayPort}`; return `ws://${this.relayAddress}:${this.relayPort}`;
} }
receiveData() { receiveData() {
const relay = this.getRelayURL(); const relay = this.getRelayURL();
if (this.transferName.length > 0) { if (this.transferName.length > 0) {
this.isReceiving = true;
this.receiveSuccess = false;
this.tauriService.receive(relay, this.transferName) this.tauriService.receive(relay, this.transferName)
.then(sendDataReturn => console.log(sendDataReturn + ' Data received successfully')) .then(sendDataReturn => {
console.log(sendDataReturn + ' Data received successfully')
this.receiveSuccess = true;
setTimeout(() => {
this.reset();
}, 5000);
})
.catch(error => console.error('Error receiving data:', error)); .catch(error => console.error('Error receiving data:', error));
} else { } else {
console.error('No files to receive.'); console.error('No files to receive.');

View file

@ -2,11 +2,11 @@
<h2>Sender</h2> <h2>Sender</h2>
<p>Hier können Sie Dateien senden.</p> <p>Hier können Sie Dateien senden.</p>
<div *ngIf="!sendingInProgress && !sendingSuccess" class="form-group"> <div *ngIf="!sendingInProgress && !sendingSuccess && !isRelayServerSet" class="form-group">
<label for="relayAddress">Relay Server Adresse:</label> <label for="relayAddress">Relay Server Adresse:</label>
<input type="text" id="relayAddress" [(ngModel)]="relayAddress" placeholder="::1"> <input type="text" id="relayAddress" [(ngModel)]="relayAddress" placeholder="::1">
</div> </div>
<div *ngIf="!sendingInProgress && !sendingSuccess" class="form-group"> <div *ngIf="!sendingInProgress && !sendingSuccess && !isPortSet" class="form-group">
<label for="relayPort">Port:</label> <label for="relayPort">Port:</label>
<input type="text" id="relayPort" [(ngModel)]="relayPort" placeholder="8000"> <input type="text" id="relayPort" [(ngModel)]="relayPort" placeholder="8000">
</div> </div>
@ -22,7 +22,7 @@
<div *ngIf="!sendingInProgress && !sendingSuccess" class="form-group"> <div *ngIf="!sendingInProgress && !sendingSuccess" class="form-group">
<button (click)="sendData()" [disabled]="sendingInProgress">Daten senden</button> <button (click)="sendData()" [disabled]="sendingInProgress">Daten senden</button>
</div> </div>
<div class="form-group"> <div *ngIf="!sendingInProgress && !sendingSuccess" class="form-group">
<button (click)="redirectToHome()">Startseite</button> <button (click)="redirectToHome()">Startseite</button>
</div> </div>
<div *ngIf="sendingInProgress"> <div *ngIf="sendingInProgress">
@ -33,7 +33,7 @@
<p>Data sent successfully! Transfer Name: {{ transferName }}</p> <p>Data sent successfully! Transfer Name: {{ transferName }}</p>
</div> </div>
<div *ngIf="!sendingInProgress && !sendingSuccess && transferName === null"> <div *ngIf="!sendingInProgress && !sendingSuccess && transferName === ''">
<p>No data being sent.</p> <p>No data being sent.</p>
</div> </div>

View file

@ -1,10 +1,11 @@
import { Component, ChangeDetectorRef } from '@angular/core'; import { Component, ChangeDetectorRef, OnInit } from '@angular/core';
import { TauriService } from '../../services/tauri.service'; import { TauriService } from '../../services/tauri.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FileResponse, open } from '@tauri-apps/plugin-dialog'; import { FileResponse, open } from '@tauri-apps/plugin-dialog';
import { listen } from '@tauri-apps/api/event'; import { listen } from '@tauri-apps/api/event';
import { StorageService } from '../../services/storage.service';
@Component({ @Component({
selector: 'app-sender', selector: 'app-sender',
@ -13,18 +14,32 @@ import { listen } from '@tauri-apps/api/event';
templateUrl: './sender.component.html', templateUrl: './sender.component.html',
styleUrls: ['./sender.component.css'] styleUrls: ['./sender.component.css']
}) })
export class SenderComponent { export class SenderComponent implements OnInit {
files: string[] = []; files: string[] = [];
fileNames: string[] = []; fileNames: string[] = [];
relayAddress: string = ''; relayAddress: string = '';
relayPort?: number | null; relayPort?: number | null;
sendingInProgress = false; sendingInProgress = false;
sendingSuccess = false; sendingSuccess = false;
isRelayServerSet = false;
isPortSet = false;
transferName: string = ""; transferName: string = "";
constructor(private tauriService: TauriService, private router: Router, private cdr: ChangeDetectorRef) { constructor(private tauriService: TauriService, private router: Router, private cdr: ChangeDetectorRef, private storage: StorageService) {
this.listenToTransferEvents(); this.listenToTransferEvents();
} }
ngOnInit(): void {
if(this.storage.getLocalEntry('relayServer')) {
this.isRelayServerSet = true;
this.relayAddress = this.storage.getLocalEntry('relayServer')
}
if(this.storage.getLocalEntry('port')) {
this.isPortSet = true;
this.relayPort = this.storage.getLocalEntry('port')
}
console.log("Moin")
}
redirectToHome() { redirectToHome() {
this.router.navigate(['']) this.router.navigate([''])
} }
@ -39,11 +54,9 @@ export class SenderComponent {
reset() { reset() {
this.files = []; this.files = [];
this.fileNames = []; this.fileNames = [];
this.relayAddress = '';
this.sendingInProgress = false; this.sendingInProgress = false;
this.sendingSuccess = false; this.sendingSuccess = false;
this.transferName = ''; this.transferName = '';
this.relayPort = null;
} }
async selectFile() { async selectFile() {

View file

@ -0,0 +1,121 @@
body {
font-family: Arial, sans-serif;
}
.logo.angular:hover {
filter: drop-shadow(0 0 2em #e32727);
}
/* Zentriert das Menü horizontal und vertikal */
.menu-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh; /* Höhe der gesamten Ansichtshöhe */
}
.menu {
background-color: #333;
padding: 20px;
border-radius: 8px;
}
.menu ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}
.menu ul li {
margin: 0 20px; /* Abstand zwischen den Menüelementen */
}
.menu ul li a {
color: white;
text-decoration: none;
font-size: 18px;
}
.menu ul li a:hover {
text-decoration: underline;
}
.burger-menu {
position: relative;
width: 100%;
}
.burger-icon {
font-size: 30px;
cursor: pointer;
}
.burger-menu-menu {
display: none;
position: absolute;
top: 40px;
left: 0;
background-color: white;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
width: 250px;
padding: 16px;
border-radius: 8px;
box-sizing: border-box;
}
.burger-menu-menu.show {
display: block;
}
.burger-menu-menu h2 {
margin-top: 0;
color: #333;
}
.burger-menu-menu label, .burger-menu-menu input, .burger-menu-menu select {
display: block;
width: 100%;
margin-bottom: 10px;
box-sizing: border-box;
}
.burger-menu-menu label {
color: #333;
}
.burger-menu-menu input, .burger-menu-menu select {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
.save-button {
width: 100%;
padding: 10px;
background-color: #4CAF50;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
.save-button:hover {
background-color: #45a049;
}
.reset-button {
padding-top: 2rem;
width: 100%;
padding: 10px;
background-color: #ff0000;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
.reset-button:hover {
background-color: #da1e1e;
}

View file

@ -0,0 +1,17 @@
<div class="burger-menu">
<div class="burger-icon" (click)="toggleMenu()">
&#9776;
</div>
<div class="burger-menu-menu" [ngClass]="{'show': menuVisible}">
<h2>Einstellungen</h2>
<label for="variable1">Relayserver Address:</label>
<input type="text" id="variable1" [(ngModel)]="settings.relayServer">
<label for="variable2">Port:</label>
<input type="number" id="variable2" [(ngModel)]="settings.port">
<button class="save-button" (click)="saveSettings()">Save Settings</button>
<button class="reset-button" (click)="resetSettings()">Reset Settings</button>
</div>
</div>

View file

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SettingsMenuComponent } from './settings-menu.component';
describe('SettingsMenuComponent', () => {
let component: SettingsMenuComponent;
let fixture: ComponentFixture<SettingsMenuComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SettingsMenuComponent]
})
.compileComponents();
fixture = TestBed.createComponent(SettingsMenuComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,49 @@
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { StorageService } from '../../services/storage.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-settings-menu',
standalone: true,
imports: [CommonModule, FormsModule],
templateUrl: './settings-menu.component.html',
styleUrl: './settings-menu.component.css'
})
export class SettingsMenuComponent implements OnInit {
constructor(private storage: StorageService, private router: Router) {}
menuVisible = false;
settings = {
relayServer: '',
port: 0,
};
ngOnInit(): void {
if(this.storage.getLocalEntry('relayServer')) {
this.settings.relayServer = this.storage.getLocalEntry('relayServer');
}
if(this.storage.getLocalEntry('port')) {
this.settings.port = this.storage.getLocalEntry('port');
}
}
toggleMenu(): void {
this.menuVisible = !this.menuVisible;
}
saveSettings(): void {
this.storage.setLocalEntry('relayServer', this.settings.relayServer)
this.storage.setLocalEntry('port', this.settings.port)
alert("The settings have been saved!");
this.menuVisible = !this.menuVisible;
}
resetSettings(): void {
this.settings.relayServer = '';
this.settings.port = 0;
this.storage.clearLocal();
alert("The settings have been reset!")
this.menuVisible = !this.menuVisible;
}
}

View file

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { StorageService } from './storage.service';
describe('StorageService', () => {
let service: StorageService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(StorageService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View file

@ -0,0 +1,58 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class StorageService {
// ----------------- Session ------------------------
// Ruft einen Wert aus dem sessionStorage ab
getSessionEntry(key: string): any {
const item = sessionStorage.getItem(key);
return item ? JSON.parse(item) : null;
}
public setSessionEntry(key: string, data: unknown): void {
sessionStorage.setItem(key, JSON.stringify(data));
}
public deleteSessionEntry(key: string): void {
sessionStorage.removeItem(key);
}
public clearSession(): void {
sessionStorage.clear();
}
public isSessionEmpty(): boolean {
return sessionStorage.length === 0;
}
// ----------------- Local ------------------------
public setLocalEntry(key: string, data: unknown): void {
localStorage.setItem(key, JSON.stringify(data));
}
public getLocalEntry(key: string): any {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
}
public deleteLocalEntry(key: string): void {
localStorage.removeItem(key);
}
public clearLocal(): void {
localStorage.clear();
}
public isLocalEmpty(): boolean {
return localStorage.length === 0;
}
// ----------------- General ------------------------
public clearAll(): void {
this.clearLocal();
this.clearSession();
}
}