Blog: Latest Entries (15):


Tradfri: Wenn Alexa die Lampen nicht mehr erreicht

Heute konnte Alexa die Tradfri Lampen im Wohnzimmer nicht an und aus machen. Alle anderen Räume funktionierten wie gehabt. Nach viel hin und her, geht es nun wieder. OK.. wir haben jetzt 2x "Tradfri Bulb 5" in der Liste der Smarthome-Geräte.

Am Ende hatte das Gateway die Verknüpfung zum Schalter/Dimmer wohl irgendwie verloren. Nachdem der noch mal neu am Gateway angemeldet wurde und die Lampen diesem wieder zugeordnet wurden (also daneben legen und den Schalter 10sec lang drücken).

bbcode-image


War nicht das erste Mal, dass eine Fernbedienung solch ein Problem hatte. Tradfri ist am Ende doch etwas instabil.

Blackmagic Intensity: HDMI-Out Monitor

Das Problem beim Capturen von Videos ist an sich immer die Latenz. Die Verarbeitung des Signals braucht eben bis die Encoder-Hardware durchlaufen wird und dass kann einige MS bis Sekunden dauern. Den Effekt kann man allein schon bei TV-Geräten sehen, wenn man Bild und Ton von z.B. einem Sat-Receiver getrennt überträgt. Da kann es schnell passieren, dass der Ton im Soundsystem ein wenig schneller verarbeitet wird als das Bild im TV-Gerät und so der Ton immer schon etwas weiter ist. AV-Receiver sorgen dafür, dass alles synchron bleiben oder bei anderen Soundsytemen kann eine Verzögerung per Hand einstellen, um Ton und Bild synchron zu halten.

bbcode-image


Bei der Blackmagic Intensity hat man die Möglichkeit am HDMI-Out einen weiteren Monitor zu betreiben der das Bild un den Ton verzögerungsfrei darstellt, während die Darstellung und Verarbeitung auf dem PC (Capture-System) verzögert dargestellt werden kann. Wenn man einen SNES-Mini anschließt kann man sehr gut nachvollziehen, warum man das auch braucht. Ohne Monitor hängt das Bild immer etwas hinterher. Wenn man in Super Mario World springt, wird das Bild auf dem PC diese Aktion erst eine halbe Sekunde später anzeigen. Das Spiel wird dadurch also an sich unspielbar. Sollten noch Filter auf das Bild angewendet werden oder es mit anderen Video-Quellen abgemischt werden, kann die Verzögerung sogar noch größer werden.

Über den HDMI-Out merkt man wirklich keine Verzögerung und kann normal spielen.


Down im Dezember

Es wird mal Zeit sich der Zukunft zu zuwenden und nicht mehr in der Vergangenheit zu leben. Deswegen werde ich endlich mal alle meine Seiten und Projekte in Docker-Container verfrachten und mit Traefik meinen Server neu strukturieren. Deswegen kann es im Dezember bei meinem Blog und MP4toGIF.com zu längeren Downzeiten im Dezember kommen. Ich überlege auch einen günstigen zweiten Server nur für Emails zu nehmen.

Das ganze sollte mir dann auch die Möglichkeiten geben spontan mal andere Dienste zu deployen. Im Kopf habe ich da so:

* Passbolt (als Ersatz für KeePasssXC)
* ownCloud um von OneDrive weg zu kommen
* und vielleicht Satis um meine PHP-Libs zu bündeln

Ich hoffe mal, dass alles ganz einfach und super funktioniert :-)

Amazon Echo Flex: Zuviel Geld für zuwenig Klang

Der Amazon Echo Flex sah auf den ersten Blick nach einem perfekten Gerät für Küche oder Bad aus. Der passt in eine Steckdose und steht nirgends im Weg. Er ist relativ günstig und wenn er nur etwas schlechter wäre als ein Echo Dot, wäre er immer noch sehr gut.
Leider ist aber die Klangqualität nicht etwas schlechter sondern sehr viel schlechter als beim Dot. Musik ist wirklich kein Highlight, aber die Stimme von Alexa klingt nochmals schlimmer. Extrem blechernd. Der Lautsprecher darin scheint billiger als nötig gewesen zu sein. Selbst ein "OK" von Alexa klingt einfach nicht mehr schön.

bbcode-image
Echo Flex in der Küche (mit Leonardo)


Wenn man bedenkt, dass man den Flex momentan für 19,99 EUR bekommt und den Dot für 22 EUR, sollte man nicht mal einen Gedanken an den Flex und lieber einen Gedanken mehr an seine Ohren verschwenden und den Dot kaufen!

VSCode: PHP Debugging

Es war ein harter Kampf.. aber ich war siegreich. Nachdem ich durch den Wechsel meines Arbeitgebers auch den Zugriff auf Intellij + PHP-Plugin einbüßen musste, bin ich jetzt vollständig auf VSCode gewechselt.

Wie ich XDebug + VSCode + Docker zum Laufen bekommen habe.

Dockerfile (nur der wichtige Teil):

RUN pecl install xdebug-2.8.0 && docker-php-ext-enable xdebug
RUN echo 'zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so"' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.remote_port=9000' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.remote_enable=1' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.remote_host=host.docker.internal' >> /usr/local/etc/php/php.ini


Lokale php.ini (ich habe 2.8.0 herunter geladen und als php_xdebug.dll gespeichert):

zend_extension=c:\php\ext\php_xdebug.dll

#.....

[XDebug]
xdebug.remote_enable = 1
xdebug.remote_autostart = 1


Dann habe ich dieses Plugin in VSCode installiert. Mit Hilfe dieses Boilerplate-Projekts habe ich mir eine passende .vscode/launch.json gebaut.


{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9000,
"pathMappings": {
"/var/www/html": "${workspaceFolder}/"
},
"xdebugSettings": {
"max_data": 65535,
"show_hidden": 1,
"max_children": 100,
"max_depth": 5
}
}
]
}


Dann VSCode neugeladen. Docker gestartet und in die Debug-Ansicht von VSCode gewechselt.

bbcode-image


Dort das ""Listen for XDebug" Profile starten und es sollte funktionieren.

bbcode-image


PHPStorm/Intellij ist da viel einfacher, weil man nicht selbst noch JSON-Dateien anlegen und editieren muss. Aber es läuft!


Shopware 6: Ein einfaches Beispiel-Plugin

Plugins für Shopware 6 zu schreiben ist an sich garnicht so unterschiedlich zu dem selben Vorgang für Shopware 5. Was nur anders geworden ist, dass Shopware eigene XMLs und Enlight-Components durch den Composer und Symfony abgelöst wurden. Man kann nun wirklich Namespaces definieren, die unabhängig vom Plugin-Namen sind und es ist kein Problem mehr den Composer mit Plugins zu verwenden, sondern es ist jetzt der zu gehende Weg.

Setup

Wie gehabt kann man sein Plugin unter custom/plugins anlegen.


custom/plugins/HPrOrderExample


Zu erst sollte man mit der composer.json anfangen.


{
"name": "hpr/order-example",
"description": "Order Example",
"version": "v1.0.1",
"license": "MIT",
"authors": [
{
"name": "Hannes Pries"
}
],
"require": {
"shopware/platform": "dev-master"
},
"type": "shopware-platform-plugin",
"autoload": {
"psr-4": {
"HPr\\OrderExample": "src/"
}
},
"extra": {
"shopware-plugin-class": "HPr\\OrderExample\\OrderExample",
"copyright": "(c) by Hannes Pries",
"label": {
"de-DE": "Order-Beispiel für SW6",
"en-GB": "Order-Example for SW6"
}
}
}


Wichtig in der composer.json ist einmal der PSR-4 Namespace den man auf das src/ Verzeichnis setzt und der "extra" Teil. Dort wird alles definiert, was mit Shopware zu tun hat. Hier wird auch die zentrale Plugin-Class angegeben, die nicht mehr wie in Shopware 5 den selben Namen des Verzeichnisses des Plugins haben muss. Auch sieht man hier dass der Namespace-Name nichts mehr mit dem Verzeichniss-Namen zu tun hat.


Wir könnten durch die composer.json das Plugin auch komplett außerhalb der Shopware-Installation entwickeln, weil die gesamte Plattform als Dependency eingebunden ist. Deswegen müssen wir auch einmal den Composer ausführen.


php composer install


Plugin programmieren
Nun fangen wir mit dem Schreiben des Plugins an.

Die Plugin-Klasse enthält erst einmal keine weitere Logik:


<?php
namespace HPr\OrderExample;

use Shopware\Core\Framework\Plugin;

class OrderExample extends Plugin{

}


Wir wollen auf ein Event reagieren. Dafür benutzen wir eine Subscriber-Klasse. Während man diese in Shopware 5 nicht unbedingt brauchte und alles in der Plugin-Klasse erldedigen konnte, muss man nun eine extra Klasse nutzen und diese auch in der services.xml eintragen. Die Id des Services ist der fullqualified-classname des Subscribers

src/Resources/services.xml

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="HPr\OrderExample\Subscribers\OnOrderSaved">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>

Resources ist vordefiniert, kann aber in der Plugin-Klasse angepasst werden, so dass diese Dateien auch in einem anderen Package liegen könnten.

src/Subscribers/OnOrderSaved

<?php
namespace HPr\OrderExample\Subscribers;

use Shopware\Core\Checkout\Order\OrderEvents;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class OnOrderSaved implements EventSubscriberInterface {
/**
* @return array The event names to listen to
*/
public static function getSubscribedEvents()
{
return [
OrderEvents::ORDER_WRITTEN_EVENT => ['dumpOrderData']
];
}

public function dumpOrderData(EntityWrittenEvent $event) {
file_put_contents('/var/test/orderdump.json', json_encode($event->getContext()));
}
}

Hier sieht man, dass nur noch Symfony benutzt wird und keine Shopware eigenen Events.

Wir schreiben einfach die Order-Entity, die gespeichert wurde in eine Datei. Dort können wir UUID und ähnliches der Order finden.

Das ganze kann man dann weiter ausbauen und auf andere Order-Events (die man alle in der OrderEvents.php finden kann) reagieren.

Installieren

Damit ist das Plugin auch schon soweit fertig. Den Composer haben wir schon ausgeführt (ansonsten müssen wir es spätestens jetzt machen).

Nun geht es über die UI oder die Console weiter. Dort wird das Plugin installiert und und aktiviert.

bbcode-image


bbcode-image


Wenn man nun eine Bestellung ausführt wird, deren Entity in die oben angegebene Datei geschrieben.

Alexa und das Küchen Licht

Heute wurde die Küche Tradfridi- und Alexarisiert. Beim Einrichten der Routinen kam es aber zu dem Problem, das "Alexa, Küchenlicht an" nur dazu führte, dass Alexa das nur damit quittierte "Das Gerät Küchenlicht konnte nicht gefunden werden". Das war seltsam denn z.B. "Alexa, Schlafzimmer Licht an" ohne Probleme funktionierte. "Küche Licht an" klingt aber doof. Vielleicht kommen einige jetzt schon auf die Lösung. "Alexa, Küchen Licht an" funktioniert. Also wenn man das Problem hat, einfach mal versuchen Worte auseinander zu schreiben.

bbcode-image


Über die Kämpfe mit dem Ikea Tradfri-System schreibe ich ein anders mal. Spoiler: Meine Nerven haben es nur knapp überlebt.

EasyComponent.JS: Framework Beispiel

Frameworks gelten ganz ganz oft als etwas sehr kompliziertes und mächtiges Werkzeug, das nur von wenigen auserwählten entwickelt und designed wird. Wenn ein Framework etwas nicht kann wird es meistens so hingenommen und darauf gehofft, dass es vielleicht doch noch irgendwann mal eingebaut wird. Meistens würde man sich nie trauen, sich dabei einzubringen oder einzumischen.

Man selbst ist ja einfacher "Anwender" und wie die eigenen Anwender, die das eigene Programm nutzen, das wieder das Framework nutzt, sollte man sich nicht die Dinge einmischen, von denen man keine Ahnung hat.

Ich habe über die Jahre doch ein paar Frameworks gebaut. Gute, schlechte, noch schlechtere und auch welche, die durch die allgemeine Frameworks ersetzt wurden. Auch mal ein Bugfix für ein vorhandenes Framework war dabei.

Wichtig ist dabei, dass man sich klar wird, dass Frameworks im Kern meistens alles andere als hoch komplex sind. Das würde schon dem
Zweck des Frameworks widersprechen, das ja für möglichst viele Anwendungszwecke funktionieren soll. Der Core ist meistens sehr einfach und klar strukturiert. Komplexität kommt meistens über Zusatzfunkionen rein, die wieder rum nur die Kernfunktionen bedienen. Wenn diese Kernfunktionen gemischt werden und kann es am Anfang sehr unübersichtlich erscheinen, weil teilweise nicht ganz klar ist, was wofür da ist.

Bei React mit Hooks kann selbst das Mischen von useState und useEffect teilweise kompliziert sein, weil aus der Sicht des Entwicklers vielleicht, von diesen Funktionen was anderes Erwartet wird, als im Framework-Kern damit wirklich erreicht wird.

Frameworks machen keine Zauberrei aber dafür sehr viel Referenz-Verwaltung. Meiner Erfahrung nach beschäftigt man sich im Framework-Kern zu 75% allein damit Instanzen und Referenzen zu erzeugen und zu verwalten.

Um das ganze etwas zu verdeutlichen habe ich mich einmal hingesetzt und in unter einer Stunde (hatte ich mir auch so vorgegeben) ein kleines Framework gebaut, das useState und useEffect reimplementiert und zeigt, wie man das Verhalten dieser Funktionen nutzt, aber auch, welche Funktion für das Framework wirklich dahinter steckt. Weil am Ende kommt man zu meist immer zu selben Strukturen, die bei allen Frameworks immer nur etwas anders benannt und implementiert sind.

Github - EasyComponent.JS Code & Präsentation
https://github.com/annonyme/easycomponents_presentation

Docker: sFTP-Server für schnelle Tests

Manchmal muss den Upload von Dateien testen. Nicht immer nutzt man etwas wie S3 sondern oft auch noch ganz klassische Umgebungen mit SCP oder sFTP. Wenn man schnell und unkompliziert den Upload auf einen sFTP-Server testen will, kann sich so einen ganz schnell und einfach mit Docker erzeugen.


docker run -p 2222:22 -d atmoz/sftp foo:pass:::upload

https://github.com/fixate/docker-sftp

man kann sich dann auf localhost:2222 mit dem Benutzer foo und dem Passwort pass verbinden. Für Dateien steht das Upload-Verzeichnis bereit. Wenn man ihn nicht mehr braucht, wirft man den Container einfach weg und kann das nächste mal sauber mit einem neuen starten.

Wann ist eine Software "unwartbar"?

Jeder kennt Software, die man nicht mehr anfassen möchte. Man sagt, die Software wäre nicht mehr wartbar. Aber was bedeutet das überhaupt?


Die Definition von Wahnsinn ist, immer wieder das Gleiche zu tun und andere Ergebnisse zu erwarten.

von irgendwem.. vielleicht Einstein

Wenn eine Software unwartbar wird, gilt etwas sehr ähnliches.


Die Definition von unwartbar ist, an zwei augenscheinlich gleich funktionierenden Stellen etwas zu ändern und bei beiden das selbe Ergebnis zu erwarten... das es dann aber nicht ist!

von Hannes Pries... nach einen entsprechenden Tag

Oft ist solche Software organisch gewachsen. Organisch gewachsen bedeutet in diesem Fall, dass man nie das grundlegende System erweitert und verbessert hat, sondern einfach neue Funktionen drum herum gebaut hat. Auch wird oft Code kopiert und im Laufe der Zeit immer nur die einzelnen Code-Blöcke angepasst, wo es nötig ist und die anderen so belassen. Besser wäre es gewesen, den Code auszulagern, so dass an allen Stellen die Änderungen greifen.

Oft sind es gar nicht die ganz alten Code-Teile der aller ersten Version, die die Probleme machen, weil diese noch einem Konzept folgten. Mit der Zeit ist das Konzept verloren gegangen und die damaligen Entwickler sind oft schon lange nicht mehr dabei. Es gibt natürlich keine Doku, Namespaces und eine besonders übersichtliche Sortierung von Klassen sind meistens nicht vorhanden, gab es zu der Zeit einfach nicht oder wurden durch die ganzen Erweiterungen selbst zerstört.
Mit der Zeit setzt sich die Annahme durch, dass der damalige Code einfach schlecht war und man es erneuern sollte, wenn man etwas neues programmiert. Das führt dazu, dass jeder das auch macht und plötzlich 3-4 Implementierungen für ein und das selbe gibt.
Dumm nur, dass auch alle diese Implementierungen auch immer verwendet werden und so sich niemand traut eine der Implementierungen abzuschalten, weil es nicht der eigene Code ist und man sich nicht sicher ist, ob es wirklich 100%ig den selben Funktionsumfang hat.

Aber irgendwann muss man daran und dann baut man einfach etwas wieder ran und entfernt nicht einfach die Implementierung und nutzt die aktuellste.

Lustig ist auch, dass man oft gegen Ende der Lebenszeit einer Software, wenn man die Strukturen für einen Rewrite analysiert, feststellt, was das grundlegende alte Framework schon alles konnte und vieles was man später mit viel Aufwand eingebaut hat, schon lange da war. Oft auch sogar in einer gar nicht so schlechten Implementierung.

Jeder hat bei so etwas genau so mitgemacht, oder? Zeitdruck... neu bauen und nicht alten Code lesen. Wirklich mal mysqli-Funktionen gegen PDO ersetzen? Wäre toll, aber wer will sich wirklich die Arbeit machen, weil es ja doch alles irgendwie funktioniert. Das System verwendet viele PHP-Dateien und keine zentrale index.php? Kann man ja schnell bauen.. macht man aber nie und muss in vielen Dateien oft die selben Dinge ändern.

Was ist die Lösung? Sich klar werden, dass es nichts mehr bringt und das System sauber neu schreiben. Nicht für sich (naja.. doch irgendwie schon), sondern für andere Entwickler. Es muss ein System sein, wo man von ausgeht, dass es für jeden Fall eine Lösung mitbringt. Das System wird den selben Weg gehen und man muss versuchen schon ganz am Anfang anfangen gegen zu steuern auch noch kein anderer daran mit arbeitet.


Keep it simple! Keep it clean!

hat das schon mal wer anderes gesagt? Bestimmt!

Wenig Code, klare Interfaces mit 100%ig aussagekräftige Namen. Die Codevervollständigung ist die Suche nach der richtigen Klasse, also müssen alle Klassen richtig benannt sein.

Es ist alle schwerer als man denkt, aber Frameworks und Standards wie PSR bei PHP helfen da sehr. Sich einfach auf den Stil und die Konventionen des Frameworks einlassen und sich aneignen. Dann klappt es schon. Auch wenn es schwer ist.

Spring Boot mit HTTPS: schnelle Lösung

Gerade wenn man Apps (PWAs) entwickelt, die zwingend HTTPS brauchen, weil man auf Dinge wie die interne Kamera des Geräts zugreifen möchte, kommt man zu dem Problem auch die Middleware mit HTTPS betreiben zu müssen. Kein Browser mag Mixed-Content. Wenn die Middleware mit Spring Boot geschrieben ist, kommt man aber auch da ziemlich schnell und einfach zu einer Lösung.
Das funktioniert sogar ohne komplexe Keystore Aktionen und irgendwelchen Signieren von gebauten Artefakten.

Die einfachste Lösung ist sich ein PKCS#12-Certificate (als das als Datei, PKCS#11 ist das von den Smartcards) zu erzeugen und direkt als Keystore zu nutzen.


keytool -genkeypair -alias pkcs12test -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore pkcs12test.p12 -validity 3650


Neben dem Alias sollte man auch den Dateinamen der p12-Datei anpassen. Danach muss man viele Daten angeben (die man sonst in openssl in der Conf-Datei ablegen würde). Die p12-Datei kann man nun einfach im resources-Bereich im Default-Package ablegen (bzw. auch in jedem anderen Package, wo es per getResource erreichbar ist).

Danach muss man die Daten nur noch in der application.properties eintragen.


server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:pkcs12test.p12
server.ssl.key-store-password=your_password
server.ssl.key-alias=pkcs12test


Danach sollte Spring Boot wie vorher auf dem konfigurierten Port starten, aber ab jetzt nur noch per HTTPS erreichbar sein.

Das Certificate ist natürlich nur self-signed und eignet sich nur für Dev-Umgebungen. Bevor die PWA auf die Middleware zu greifen kann, muss man mit dem Browser die Middleware einmal aufrufen und den Zugriff für den Browser erlauben. Danach sollte es dann gehen.

Die ausführlichere Anleitung findet man hier:
https://www.baeldung.com/spring-boot-https-self-signed-certificate

HDMI Capturen mit Blackmagic Intensity Pro

Über die Jahre hatte ich schon mit vielen Videokarten zu tun. Von den klassischen Fast Karten wie der Movie Machine 2 oder dem AV.master zu an sich fast allen Miro/Pinnacle Karten wie DC10, DC20 und DC30. Auch so exotische Teile wie die Iomega Buz (mit integrierten SCSI-Controller).

bbcode-image


Dann kam lange Zeit nichts mehr weil CAmcorder Firewire hatten oder man alte schon digitalisierte Video nur noch immer wieder hin und her codiert hat. Dann kam aber die Idee auf mal Mario Kart von der Switch auf Twitch zu streamen. Bevor ich mich weiter mit einem kleinen Konzept beschäftigen wollte, dass mit abends mal spontan einfiel, wollte ich wissen, ob so etwas überhaupt vernünftig geht.

Mein erster Versuch war noch rein PC-basiert und ich wollte Testen ob ich ein Spiel (Ion Fury) und eine Webcam (Dogcam) streamen kann ohne dass mein doch schon relativ alter PC dabei in die Knie geht. Hardwarebeschleunigung beim Encodieren mit meiner Radeon HD 7990 wollte ich dann auch gleich testen. Obwohl ich nur sehr langsame CPUs habe, lief alles erstaunlich gut und ich habe gelernt den Studio-Modus von OBS zu nutzen.

bbcode-image


Da alles gut lief, ging es nun darum eine HDMI-Quelle an den PC anzuschließen. Was nutzt man da, wenn man nicht gleich viel Geld ausgeben will? AVerMedia ist teuer, Elgato auch, eine China No-Name Karte wollte ich dann aber auch nicht riskieren.
Also habe ich mich für eine günstige Lösung der Marke Blackmagic entschieden. Die Blackmagic Intensity Pro in der nicht-4K Edition. Der Vorteil ist auch, dass ich mir noch eine Kabelpeitsche dazu kaufen könnte und dann wieder in der Lage wäre Analoge Quellen (z.B. einen SNES) anzuschließen.

bbcode-image


Nach dem die Karte in einem PCIe Slot nicht funktionieren wollte, funktionierte sie in einem anderen. Der war direkt unter der Grafikkarte und der Aufkleber auf der Karte bog sich bei Wärme (z.B. durch Spiele) nach oben und machte unschöne Geräusche im Lüfter der Grafikkarte. Naja.. also Aufkleber entfernt und es lief dann alles.

bbcode-image


Die Latenz ist wirklich gering. Gering.. aber SNES Mini spielen geht so nicht weil doch so 500ms Verzögerung im Bild ist. Deswegen sollte man auf jeden Fall an den HDMI-Out einen weiteren Monitor anschließen, der ohne Latenz funktioniert. Aber ich finde die Karte für so eine günstige Lösung echt gut und sie bietet viele Möglichkeiten.

Das Experiment und die Planung kann also weiter gehen!

Kurz Review: Nextcloud

Nicht jeder will für Clouddienste wie OneDrive oder Dropbox bezahlen oder hat eine so schnelle Internet Anbindung (im Upload) um sich mit einem QNAP-NAS eine eigene Lösung zu basteln. Auch sind Dropbox und OneDrive sehr eingeschränkt und erlauben kaum etwas außen dem Austausch von Dateien. Gerade als Firma oder Familie möchte man aber nicht nur Dateien tauschen, sondern auch Termine, Kontakte und Kanban-Boards teilen. Auch ist es sehr praktisch wenn man hochgeladene Text- oder Spreadsheet-Dateien direkt bearbeiten kann. Emails sind dann noch das letzte um eine wirklich vollständige Cloudlösung auch für Teams zu haben.

Wenn etwas Webspace oder einen Webserver hat, kann sich dafür einfach Nextcloud installieren. Die Collabora-Office-Integration habe ich nicht zum Laufen bekommen, aber dafür das App-Bundle für Groupware-Lösungen. Ich finde es Lösungen wie Tine 2.0 oder eGroupware überlegen und bedient sich auch einfach moderner.

bbcode-image


bbcode-image


bbcode-image


bbcode-image


bbcode-image


Gerade für kleine Firmen eine gute Alternative zu Office365, einem QNAP-NAS (mit DynDNS oder VPN) und anderen zu bezahlenden Lösungen.

React: Internals

Ich vertrete ja die Meinung, dass React erst mit der Einführung der Hooks wirklich nutzbar wurde. Vorher war alles zu aufwendig beim Prüfen des States und dem beachten der Lifecycles. Durch useState und useEffect geht jetzt alles einfacher und schneller. Wer sich schon immer gefragt hat, wo der Unterschied in useState und useReducer liegt, wird sicher diesen Artikel Under the hood of React’s hooks system sehr interessant finden und lernen, das useState einfach nur ein anderes Interface für useReducer ist.

Older posts:

Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?