Probao-Case-Study: nutzerfreundlich, schnell und SEO-optimiert

Heute möchte ich euch mein neues Projekt “Probao” vorstellen. Auf Probao teste ich Online-Dienste, die ich selbst für nützlich halte. Dabei schreibe ich auf Probao über meine Erfahrungen mit den einzelnen Diensten und wie man sie am besten nutzt.

Mein Ziel mit Probao ist es Verbrauchern die Möglichkeiten aufzuzeigen, wie man sich das Leben mit Online-Diensten erleichtern kann und dabei auch noch den ein oder anderen Euro sparen kann.

Neben meinen persönlichen Erfahrungen, die ich in den Testberichten sehr ausführlich niederschreibe, findest du auf Probao auch noch Erfahrungsberichte von anderen Nutzern.

Anders als auf so vielen anderen Plattform, können die Nutzer aber nicht irgendwelche Erfahrungsberichte hochladen oder unsachliche Hasstiraden loslassen. Alle veröffentlichten Erfahrungsberichte müssen den Qualitätsstandard von Probao entsprechen.

Das heißt Hassberichte oder übertriebenes Lobeshymnen wirst du in den Erfahrungsberichten nicht finden. Nur Erfahrungsberichte, die einen Mehrwert für dich bieten, werden wir veröffentlichen.

Wenn du selbst Erfahrungen mit Online-Diensten gemacht hast, laden wir dich ein, diese auf Probao zu veröffentlichen. Du kannst jeden Monat eine 50 Euro Amazon-Gutschein gewinnen.

Technische Umsetzung

Die technische Umsetzung basiert wie bei meinen meisten Projekten auf WordPress. Mittlerweile setze ich für Content-Projekt eigentlich immer auf WordPress. Mit WordPress bekommt man einfach die meiste Funktionalität frei Haus.

Durch das riesige Angebot an Plugins kann man mit fast jede Art von Projekt schnell umsetzen. Darüber hinaus ist WordPress schnell und Suchmaschinen-freundlich.

Ich nutze bei Probao folgende Plugins:

Als Theme benutze ich eine Eigenentwicklung, die speziell aus SEO-Gesichtspunkten optimiert ist. So lade ich nur die Javascript– und CSS-Dateien, die ich wirklich will. Mein Ziel ist es so die Ladezeiten deutlich zu verkürzen. Vor allem mobile Nutzer sollen auch komfortabel Probao nutzen können.

Herausforderungen technischer Natur

Wie schon geschrieben, war ein zentrales Ziel die Ladezeiten so weit wie möglich zu verkürzen, um ein gutes Ergebnis beim PageSpeed Insights zu bekommen.

Ferner galt es auch die Testergebnisse auf Probao ordentlich darzustellen und sie gleichzeitig als Microformats mit semantischen Informationen zu versehen, damit Suchmaschinen die Inhalte besser verstehen.

Ein dritter Punkt war die Notwendigkeit schnell und einfach Querverlinkungen zwischen unterschiedlich Erfahrungsberichten herstellen zu können. Die Querverweise sollten optisch ansprechender als einfache Links und mehr Kontext für den Leser darstellen.

Minimierung der Ladezeiten

Um die Ladezeiten so kurz wie möglich zu halten, nutze ich im Großen und Ganzen drei Strategien. Als Allererstes lasse ich Probao bei einem ordentlichen auf WordPress spezialisierten Hostinganbieter laufen.

Dies sorgt schon für die nötigen technischen Einstellungen auf dem Server. Ich muss mich weder um Caching, Komprimierung noch HTTP-Version kümmern.

Darüber hinaus sorge ich mit zwei Plugins dafür, dass Bilder stark komprimiert werden und, wenn der Besucher sie denn auslesen kann, im neuen WebP-Format ausgeliefert werden. Dies erspart meinen Besuchern viele Kilobytes und einiges an Ladezeit.

Die wichtigste Maßnahme ist aus meiner Sicht die Reduzierung der Requests. Auch wenn durch HTTP2 mehrere Downloads gleichzeitig angestoßen werden können, ist das Zusammenfassen von JavaScript und CSS immer noch ein wichtiger Teil der Optimierung.

Üblich ist dafür die Nutzung bestimmter Caching-Plugins, die die Dateien der einzelnen Plugins und von WordPress zu jeweils einer einzigen CSS- und einer einzigen JavaScript-Datei zusammenfassen.

Allerdings hatte ich mit diesem Ansatz bisher einige Probleme. Manchmal wurde dadurch die Darstellung meines Themes verhunzt. Deswegen bin ich einen anderen Weg gegangen:

In meinem WordPress-Theme pflege ich die einzelnen JavaScript- und CSS-Dateien händisch ein. Im Produktivmodus werden diese jeweils in eine Datei zusammengefügt.

So kann ich sicherstellen, welches CSS und JavaScript in meinem Theme benutzt wird und habe trotzdem keine Probleme mit der Darstellung.

Darstellung der Testergebnisse und Microformats

Testergebnis und Microformat aus benutzerdefinierten Feldern.
Testergebnis und Microformat aus benutzerdefinierten Feldern.

Eine weitere Herausforderung war die Darstellung der Testergebnisse. Zum einen wollte ich nicht jedes Mal eine Tabelle in das WordPress-Dokument einfügen. Zum anderen sollten die Daten auch als MicroFormat für Google zur Verfügung stehen.

Darüber hinaus gab es auf den Plan, zukünftig die Daten der Testberichte auch an anderer Stelle auf Probao zur Verfügung zu haben.

Aus diesem Grund werden die Testergebnisse nicht direkt im jeweiligen Testbericht gespeichert, sondern als benutzerdefinierte Felder, die jedem WordPress-Dokument zugeordnet werden können.

Das Probao-Theme stellt dann bei Vorhandensein bestimmter benutzerdefinierte Felder die entsprechenden Informationen zum Erfahrungsbericht dar.

Cross-plattform Apps mit Electron und React Teil 4

Nachdem wir im dritten Teil unsere Demoanwendung fertiggestellt haben, werden wir nun installierbare Pakete für die unterschiedlichen Plattformen bauen.

Stellvertretend für Linux-Systeme werden wir ein Debian Paket bauen. Für Windows werden wir ein Squirrel-Paket bauen und für Mac OS eine ZIP-Paket.

Wer seine App in die App Stores der jeweiligen Plattform bringen will, kann dies auch mit electron-forge machen.

Die Dokumentation gibt ausführlich Auskunft über die Möglichkeiten, wie man seine Pakete bauen kann und man sie auch gleichzeitig veröffentlichen kann.

Vorbereitung

In der package.json geben wir unserer Demo-App eine ordentliche Beschreibung und legen fest, dass wir für Linux nur ein Debian-Paket erstellen möchten.

Darüber hinaus geben wir Anwendungsdatei einen Namen und definieren den Pfad zum App-Icon.

"description": "Rebuild of the gtk3-demo-application with electron",
...
 "linux": [
    "deb
]
...
"electronPackagerConfig": {
  "packageManager": "yarn",
        "executableName": "electron-react-example",
        "icon": "./icon.svg"
}
...

Da unser Anwendungsname electron im Namen hat müssen wir die Abfrage für den Entwicklungsmodus ein ganz wenig anpassen. In der index.js fragen wir deswegen nicht nur, ob der Fahrt zur Anwendungsdatei electron enthält, sondern das electron ein Unterverzeichnis ist.

const isDevMode = process.execPath.match(/[\\/]electron[\\/]/);

Nun können wir mit unserem Linux-Build anfangen.

Linux-Build

Als Icon für die Anwendung habe ich mir von openclipart.org ein einfaches Icon heruntergeladen. Grundsätzlich reicht uns hierfür jegliche SVG- oder PNG-Datei.

Für den Linux-Build legen wir in der package.json dann unter electronInstallerDebian Werte für das Icon und die Kategorie fest.

...
"electronInstallerDebian": {
        "icon": "./icon.svg",
        "categories": [
          "Utility"
        ],
        "homepage": "https://foo.com"
      },
...

Nun können wir in der Kommandozeile mit electron-forge make unsere Anwendungen bauen. Wenn alles gut gegangen ist findet man unter out/make das Debian-Paket.

Mac OS-Build

Für den Mac-Build habe ich mir in einer virtuellen Maschine das Repo geklont und unser Icon in das icns-format konvertiert.

In der Kommandozeile habe ich dann mit NPM alle Abhängigkeiten installiert und dann wieder mit electron-forge make den Build angestoßen. Mehr war nicht notwendig.

Am Ende sollte eine ZIP-Datei stehen, die eine ausführbare Anwendung enthält.

electron-forge bietet auch die Möglichkeit DMGs für den Mac zu erstellen.

Windows-Build

Als Vorbereitung für den Windows-Build habe ich unser Icon diesmal in eine ico-Datei konvertiert. Dann habe ich wieder mit electron-forge den-Build in einer virtuellen Maschine angestoßen. Mehr ist auch hier nicht nötig.

Grundsätzlich ist es auch möglich electron-Pakete mit Wine zu bauen. Allerdings ist in der aktuellen Version von electron-forge diese Funktionalitäten nicht eingebaut. Wer trotzdem unter Linux Windows-Pakete bauen will, sollte sich das Paket electron-packager einmal anschauen.

Wir haben jetzt mit geringem Aufwand Pakete für alle bekannten Plattformen gebaut. Damit endet unser Tutorial. Ich hoffe ich konnte zeigen, dass Electron mit React eine interessante Alternative ist, wenn man plattformübergreifende Desktop-Applikation bauen möchte. 

electron-react-example für Ubuntu

electron-react-example für Mac OS

electron-react-example für Window

Unsere Anwendung passt sich gut in allen Umgebungen ein, ist mit Web-Technologien umgesetzt und hat keine externen Abhängigkeiten.

Du findest den Source-Code für dieses Tutorial auf Github: https://github.com/rockiger/electron-react-example

Created with Dictandu

Cross-plattform Apps mit Electron und React Teil 3

Im zweiten Teil haben wir unserer Electron-App einen zum jeweiligen Betriebssystem passenden Look verpasst. Dabei haben wir je nach Plattform ein passendes Stylesheet verwendet, damit sich die Anwendung gut einpasst.

In diesem Teil werden wir nun das Menü der gtk3-demo-application nachbauen. Dazu werden wir als Erstes das App-Menü der Anwendung bauen. Dieses definieren wir beim Start der App. Als zweiten Schritt werden wir ein Kontext-Menü erstellen, dass zur Laufzeit der Anwendung komponiert wird. Damit unterscheidet es sich in der Art und Weise der Definition vom App-Menü.

Abschließend werden wir noch ein paar Optimierungen für Mac OS vornehmen. Das App-Menü auf einem Mac unterscheidet sich grundlegend von den Menüs unter Windows und Linux.

App-Menü

Das App-Menü erstellen wir in der Datei src/index.js. Dort wird es während des Starts der App geladen. Als Template für das Menü verwenden wir einen Javascript-Array, der Javascript-Objekte enthält. Die Javascript Objekte entsprechen einem Menüpunkt.

Das Menü-Template hat folgende Struktur:

[
  {
    label: 'NAME',
    submenu: [
      { role: 'NAME' },
      {
        label: 'NAME',
        click () { ... }
      }
    ]
  }
]

Jeder Menüpunkt kann wiederum eigene Untermenüs enthalten. Der sich so ergebende Baum stellt das App-Menü da.

Mit der Methode buildFromTemplate erstellen wir dann das Menü-Objekt.

Zusätzlich ergänzen wir src/index.js noch um eine Funktion showMessage, die uns als Dummy-Callback dient.

import { app, BrowserWindow, Menu, dialog } from 'electron';
...
  mainWindow = null;
  });

   const showMessage = message => dialog.showMessageBox({
    type: 'info',
    message: `You activated action: "${message}"`,
    buttons: ['Close'],
  });

   const menu = Menu.buildFromTemplate([
    {
      label: 'Preferences',
      submenu: [
        {
          label: 'Prefer Dark Theme',
          type: 'checkbox',
        },
        {
          label: 'Hide Titlebar when maximized',
          type: 'checkbox',
        },
        {
          label: 'Color',
          submenu: [
            {
              label: 'Red',
              type: 'radio',
              accelerator: 'CmdOrCtrl+R',
              click: () => showMessage('Red'),
            },
            {
              label: 'Green',
              type: 'radio',
              accelerator: 'CmdOrCtrl+G',
              click: () => showMessage('Green'),
            },
            {
              label: 'Blue',
              type: 'radio',
              accelerator: 'CmdOrCtrl+B',
              click: () => showMessage('Blue'),
            },
          ],
        },
        {
          label: 'Shape',
          submenu: [
            {
              label: 'Square',
              type: 'radio',
              accelerator: 'CmdOrCtrl+S',
              click: () => showMessage('Square'),
            },
            {
              label: 'Rectangle',
              type: 'radio',
              accelerator: 'CmdOrCtrl+R',
              click: () => showMessage('Rectangle'),
            },
            {
              label: 'Oval',
              type: 'radio',
              accelerator: 'CmdOrCtrl+O',
              click: () => showMessage('Oval'),
            },
          ],
        },
        {
          label: 'Bold',
          type: 'checkbox',
          accelerator: 'CmdOrCtrl+Shift+B',
          click: () => showMessage('Bold'),
        },
      ],
    },
    {
      label: 'Help',
      submenu: [
        {
          label: 'About',
          accelerator: 'CmdOrCtrl+A',
          click: () => dialog.showMessageBox({
            type: 'info',
            title: 'about',
            message: `GTK+ Code Demos
3.22.30
Running against GTK+ 3.22.30
Program to demonstrate GTK+ functions.
(C) 1997-2013 The GTK+ Team
This program comes with absolutely no warranty.
See the GNU Lesser General Public License, 
version 2.1 or later for details.`,
            buttons: ['Close'],
          }),
        },
      ],
    },
  ]);
  Menu.setApplicationMenu(menu);
...

Anschließend sollte das Menü zu sehen sein. Das Development-Menü wird nicht mehr angezeigt. Für ein größeres Projekt könnte es sinnvoll sein, ein Development-Menü zu erhalten, dass im Entwicklungsmodus angezeigt wird und bei Auslieferung ausgeschaltet wird.

electron-react-example-global-menu

Kontext-Menu

Die Demo-App besitzt auch ein Kontextmenü zur Textbearbeitung. Um dieses nachzubauen, gehen wir etwas anders vor. Wir erstellen es nicht mehr aus einem Template, sondern komponieren es zur Laufzeit.

Dementsprechend ergänzen wir unseren Code auch nicht mehr in der src/index.js, sondern in src/app.jsx.

Als Erstes definieren wir das Menü im Konstruktor unsere App-Komponente. Weil die Menu-Klasse nur im Hauptprozess zur Verfügung steht, müssen wir auf sie über das Remote-Objekt zugreifen.

Das Menü selbst ist sehr viel einfacher als das App-Menü gehalten. Wir fügen nur ein paar Standardfunktionen und einen Trenner in das Kontext-Menü ein. Wir machen dabei ausgiebig Gebrauch von der role-Option. Diese erlaubt uns, von Electron vordefinierte Standardmenüs zu verwenden.

    const menu = new remote.Menu();
    menu.append(new remote.MenuItem({ role: 'cut' }));
    menu.append(new remote.MenuItem({ role: 'copy' }));
    menu.append(new remote.MenuItem({ role: 'paste' }));
    menu.append(new remote.MenuItem({ role: 'delete' }));
    menu.append(new remote.MenuItem({ type: 'separator' }));
    menu.append(new remote.MenuItem({ role: 'selectall' }));
    this.menu = menu;
...
    this.onContextMenu = this.onContextMenu.bind(this);

Damit wir auf das Kontext-Menü zugreifen können, definieren wir einen onContextMenu-Handler für die Textarea. Dieser macht nichts anderes, als einfach das Kontextmenü zu öffnen und mit dem Hauptfenster zu verbinden.

  onContextMenu(event) {
    event.preventDefault();
    this.menu.popup({ window: remote.getCurrentWindow() });
  }
...
    <textarea id="TextField" onKeyDown={this.onInput} onContextMenu={this.onContextMenu} />

Jetzt kann man über der Textarea mit der rechten Maustaste ein Kontext-Menü aufrufen.

electron-context-example-context-menu

Mac-Menü

Das App-Menü unter Mac OS unterscheidet sich deutlich von den App-Menüs unter Windows und Linux.

In Mac OS gibt es 3 Standard Menüs, die jeder Anwendung bereitstellen sollte:

  • window
  • help
  • services

Zu diesem Zweck stellt Electron unter Mac OS einige Standard-Menüs über Rollen bereit. Diese helfen beim Aufbau des Menüs.

Als Erstes speichern wir in src/index.js das Template für das App-Menü in einer eigenen Variablen.

Dann passen wir die Rolle unsere Hilfe-Menüs an.

Als Nächstes fügen wir die beiden anderen Unter-Menüs in unserem App-Menü ein, falls wir uns auf einem Mac befinden. Dazu verwenden wir Standard-JavaScript-Methoden, um unser Template-Array zu erweitern.

electron-react-example-macos-menu

Wenn wir nun unsere Beispielanwendung auf einem Mac starten, wird das Menü im globalen Menü von Mac OS angezeigt.

Du findest den Source-Code für dieses Tutorial auf Github: https://github.com/rockiger/electron-react-example

Im letzten Teil werden wir uns um die Paketierung mit electron-forge kümmern.

Created with Dictandu

Cross-plattform Apps mit Electron und React Teil 2

Im letzten Teil haben wir eine Electron-Anwendung geschrieben, die auf der GTK-Demo-App basiert. Wir haben die grundsätzliche Struktur der Anwendung erstellt und die Funktionalität, die die Anwendung bereitstellt hinzugefügt.

In diesem Teil möchten wir nur nun die Optik der Anwendung entsprechend anpassen. Dazu werden wir als Erstes herausfinden, auf welchem Betriebssystem und mit welchem Fenstermanager die Anwendung läuft.

Ausgestattet mit dieser Information werden wir dann das jeweilige passende Stylesheet laden, um die Anwendung nativ aussehen zu lassen.

Das Ziel ist es nicht, dass die Anwendung 100 % so aussieht, wie eine Anwendung, die mit dem Window-Toolkit des Betriebssystems geschrieben ist. Unser Ziel ist es, dass die Anwendung mit vertretbarem Aufwand so aussieht, dass sie nicht als Fremdkörper wahrgenommen wird.

In welcher Umgebung läuft die App?

Und herauszufinden, in welcher Umgebung die App läuft, müssen wir eine kleine Javascript-Abfrage beim Start der Anwendung einbauen. Mit dieser Laden wird dann, damit wir ein spezifisches Stylesheet laden können.

Dazu öffnen wir die index.html-Datei, laden style.css für plattformunabhängige Styles und fügen folgendes Javascript ein.

<link rel="stylesheet" type="text/css" href="./styles/style.css">
  <script type="text/javascript"> 
    let cssUrl = '';
    if (process.platform === 'linux') {
      const execSync = require('child_process').execSync;
      const theme = execSync('gsettings get org.gnome.desktop.interface gtk-theme').toString().toLowerCase()
      
      if (theme.includes('adwaita')) {
        cssUrl = 'adwaita.css'
      } else if (theme.includes('arc')) {
        cssUrl = 'arc.css'
      } else if (theme.includes('OSC') || theme.includes('mac')) {
        cssUrl = 'mac.css';
      } else if (theme.includes('win')) {
        cssUrl = 'win.css';
      }
      
    } else if (process.platform === 'darwin') {
        cssUrl = 'mac.css';
    } else if (process.platform === 'win32') {
        cssUrl = 'win.css';
    }
    if (cssUrl) {
        document.write('<link rel="stylesheet" type="text/css" href="./styles/'+ cssUrl +'">');
        }
  </script>

Dabei nutzen wir die process-Bibliothek von NodeJS und schauen als Erstes auf welchem Betriebssystem wir uns befinden. Befinden wir uns auf einem Mac- oder einem Windows-Rechner, nutzen wir die CSS-Datei mac.css oder win.css.

Für den Fall, dass wir uns auf einem Linux Rechner befinden haben wir noch eine kleine Besonderheit eingebaut: Wir führen mit NodeJS eine Kommandozeilen-Abfrage durch, die uns den Namen des aktuellen Themes zurückgibt. Dementsprechend verwenden wir nun die passende CSS-Datei.

Die Auswahl des Themes lässt sich beliebig erweitern, da ich persönlich das Arc-Theme verwende, werden wir uns auf dieses konzentrieren. An dieser Stelle muss jeder selbst entscheiden, mit wie viel Aufwand er Linux-User zu unterstützen möchte. Ich könnte mir vorstellen, dass ein Theme für Ubuntu-Nutzer auch noch sinnvoll wäre. Dies könnte eine gute Übung sein.

Cross-platfform Styling

Um nun ein plattform-gerechtes Styling der Einzelkomponenten zu kreieren, müssen wir diverse CSS-Dateien anlegen. Dazu erstellen wir den Ordner styles im src-Verzeichnis. Für jede angegebene CSS-Dateien müssen wir nun eine anlegen.

Als Erstes entfernen wir jegliche Inline-Styles aus unseren Komponenten. Sonst können wir diese nur mühsam überschreiben.

Im neu geschaffenen styles-Verzeichnis legen wir nun die Datei style.css an. In diese Datei kommen alle Style-Informationen, die wir vorher inline eingefügt hatten. Für die Farben legen wir CSS-Variablen fest. 

:root{
    --fg_color: #5c7080;
    --text_color: #182026;
    --bg_color: rgb(245, 248, 250);
    --borders: rgb(206, 217, 224)
}

#Layout {
    display: flex;
    flex-direction: column;
    height: 100vh;
}

.bp3-button { cursor: default; }

#TextField {
    height: 100%;
    flex-grow: 1;
    overflow: auto;
    border: none;
    resize: none;
    outline: none;
}

#StatusBar {
    background-color: var(--bg_color); 
    border-top: 1px solid var(--borders);
    color: var(--text_color);
    height: 50px;
    padding: 12px;
}

Das hat den Vorteil, dass man nur durch den Austausch der Farben schon unterschiedliche Themes erstellen kann. Soweit so gut. 

Um nun das Arc-Theme nachzubauen, benötigt man nur wenige Zeilen CSS. Zumindest für unsere Beispielanwendung.

Als Erstes überschreiben wir die CSS-Variablen für die verwendeten Farben. Dann passen wir noch Details der einzelnen Komponenten an.

:root {
    --window_bg: #e7e8eb;
    --window_fg: hsla(222, 18%, 39%, 0.8);
    --button_hover_bg: #fdfdfd;
    --button_hover_border: #D1D3DA;
    --selected_bg_color: #5294e2;
    --selected_fg_color: #ffffff;
}

.bp3-navbar {
    background-color: var(--window_bg);
    padding: 0 5px;
    height: 40px;
}
.bp3-navbar-group {
    height: 40px;
}
.bp3-button .bp3-icon {
    color: var(--window_fg)
}
.bp3-button {
    min-width: 35px;
    min-height: 30px;
}
.bp3-button.bp3-minimal:hover {
    background-color: var(--button_hover_bg);
    border: 1px solid var(--button_hover_border);
}
.bp3-menu-item { padding: 1px 7px; }
.bp3-menu-item:hover, .bp3-button.bp3-minimal:active, .bp3-button.bp3-minimal.bp3-active  { 
    background-color: var(--selected_bg_color); 
    color: var(--selected_fg_color);
}
:focus {
    outline: none;
}

#StatusBar {
    max-height: 38px;
    padding: 10px;
}

Das Ergebnis sieht wie folgt aus:

Das Gleiche machen wir noch für das MacOS- und für das Windows-Theme. Wir brauchen dafür jeweils nur wenige Zeilen CSS.

:root {
    --window_bg: #e7e8eb;
    --window_fg: hsla(222, 18%, 39%, 0.8);
    --button_hover_bg: #fdfdfd;
    --button_hover_border: #D1D3DA;
    --selected_bg_color: #5294e2;
    --selected_fg_color: #ffffff;
}

.bp3-navbar {
    background-color: var(--window_bg);
    padding: 0 5px;
    height: 40px;
}
.bp3-navbar-group {
    height: 40px;
}
.bp3-button .bp3-icon {
    color: var(--window_fg)
}
.bp3-button {
    min-width: 35px;
    min-height: 30px;
}
.bp3-button.bp3-minimal:hover {
    background-color: var(--button_hover_bg);
    border: 1px solid var(--button_hover_border);
}
.bp3-menu-item { padding: 1px 7px; }
.bp3-menu-item:hover, .bp3-button.bp3-minimal:active, .bp3-button.bp3-minimal.bp3-active  { 
    background-color: var(--selected_bg_color); 
    color: var(--selected_fg_color);
}
:focus {
    outline: none;
}

#StatusBar {
    max-height: 38px;
    padding: 10px;
}
:root {
    --window_bg: #fffff;
    --window_fg: #000000;
    --button_hover_bg: #cce8ff;
    --button_hover_border: #0078d7;
    --selected_bg_color: #cce8ff;
    --selected_fg_color: #000000;
    --bg_color: #ffffff;
    --borders: rgba(16, 22, 26, 0.1);
}

.bp3-navbar {
    background-color: var(--window_bg);
    padding: 0 10px;
    height: 40px;
    box-shadow: 0 0 0 1px var(--borders);
}
.bp3-navbar-group {
    height: 40px;
}
.bp3-button .bp3-icon {
    color: var(--window_fg)
}
.bp3-button {
    min-width: 35px;
    min-height: 30px;
    border-radius: 0;
}
.bp3-button.bp3-minimal:hover, .bp3-button.bp3-minimal:active, .bp3-button.bp3-minimal.bp3-active  {
    background-color: var(--button_hover_bg);
    border: 1px solid var(--button_hover_border);
}
.bp3-menu-item { padding: 1px 7px; }
.bp3-menu-item:hover, .bp3-button.bp3-minimal:active, .bp3-button.bp3-minimal.bp3-active  { 
    background-color: var(--selected_bg_color); 
    color: var(--selected_fg_color);
}
:focus {
    outline: none;
}

#StatusBar {
    max-height: 45px;
    padding: 15px;
}

Fairerweise muss man dazu sagen, dass alle drei Theme ohne Gradienten auskommen und somit nur wenig Änderungen brauchen. Das Gnome Standard-Theme Adwaita nachzubauen, wäre deutlich aufwendiger.

Du findest den Source-Code für dieses Tutorial auf Github: https://github.com/rockiger/electron-react-example

Im nächsten Teil werden wir das Menü der gtk3-demo-application nachbauen und noch ein wenig Feinschliff betreiben.

Created with Dictandu

Cross-plattform Apps mit Electron und React Teil 1

Mit der Kombination aus Electron und React kann man sehr einfach Desktopanwendungen für Linux, Windows und Mac entwickeln. Die Kombination aus Electron und React ermöglicht einen angenehmen Entwicklungsworkflow, der den meisten anderen GUI-Frameworks weit voraus ist.

Ein Beispiel für eine Anwendung die mit React und Electron entwickelt wurde, ist Alva. Alva ist eine Anwendung um Prototypen für Web-Komponenten zu entwerfen.

Was ist Electron?

Electron ist ein Framework, um Desktop Anwendungen mithilfe von Web-Technologien zu entwickeln. Electron basiert auf dem Chromium-Browser und dem NodeJS-Framework.

Durch die Kombination von Chromium und NodeJS kann man gleichzeitig seine Web-Entwicklungs-Kenntnisse nutzen und trotzdem auf das Dateisystem bzw. die Hardware des Host-Rechners zugreifen.

Bekannte Beispiele für Anwendungen, die mit Electron geschrieben worden sind, sind die Text-Editor Atom und Visual Studio Code, die Desktop-Anwendung von Skype und der Slack Chat-Client. Electron ist vor allem bei Startups aus dem Silicon Valley sehr populär.

Durch die Verwendbarkeit von JavaScript-Bibliotheken kann man bei der Entwicklung von Electron-Apps auf einen riesigen Vorrat an nützlichen Frameworks zurückgreifen. Daher kann man auch React mit Electron verwenden.

Was ist React?

React ist eine JavaScript-Bibliothek zur Entwicklung von Benutzerschnittstellen. React wird von Facebook entwickelt und eignet sich besonders für die Entwicklung von Single-Page-Apps, wie sie häufig mit Electron entwickelt werden.

Das Besondere an der GUI-Entwicklung mit React ist, dass man seine Benutzerschnittstelle deklarativ entwickelt. Das heißt, man muss seine Web-Komponenten nicht selber verändern, wenn sich der zugrundeliegende Zustand der Anwendung verändert. Durch React passen sich die einzelnen Komponenten automatisch dem aktuellen Zustand der Anwendung an.

Dieses reaktive Verhalten ist auch der Namensgeber für React. Darüber hinaus bietet React noch einige interessanten Funktionen zum Zustands-Management, die bei Bedarf auch noch durch weitere Bibliotheken erweitert werden kann.

Warum Electron + React?

Die Kombination aus React und Electron bildet ein GUI-Framework, dass sehr gut dokumentiert ist, sehr Entwickler freundlich ist und auf ein riesiges Ökosystem zurückgreifen kann. Alles Eigenschaften, die die gängigen GUI-Frameworks, speziell unter Linux, so nicht bieten.

Erste Schritte

Im Folgenden gehe ich von grundlegenden JavaScript-Kenntnissen und Basiswissen in der Verwendung von Nodejs aus.

Als Erstes müssen wir Electron mit React aufsetzen. Das geht am leichtesten mit Electron Forge. Electron Forge ist ein Command-Line-Projekt. Mit dem sich Electron Projekte schnell aufsetzen lassen. Es stehen mehrere Templates zur Verfügung um schnell das passende Framework für Electron aufzusetzen. Neben React kann man beispielsweise auch TypeScript oder Angular mit Electron aufsetzen.

Um Electron Forge zu installieren und dann ein neues Electron-React Projekt zu starten, gibst du in einem Terminal folgenden Code ein:

npm install -g electron-forge
electron-forge init electron-react-example --template=react
cd electron-react-example
npm install
electron-forge start

Der Prozess dauert ein wenig, da die komplette Runtime von Electron heruntergeladen wird. Am Ende sollte dic ein Electron Fenster mit einer neuen React-App begrüßen.

Electron-React-Example

Eine weitere beliebte alternative Electron Apps mit React zu erstellen ist das Electron React Boilerplate. Ich habe mich für Electron Forge entschieden, weil die Optionen zur Paketierung der App aus meiner Sicht umfangreicher sind und besser funktionieren. Electron React Boilerplate bietet sehr umfangreiche Voreinstellungen für React, die mir mehr im Weg standen, als sie mir genutzt haben.

Warum kein create-react-app?

Ein Wort noch zu Create React App. Create React App ist das offizielle Tool von Facebook um neue React Apps zu erstellen. Allerdings ist Create React App ganz klar auf “echte” Web-Applikationen ausgelegt.

So verhindert Create React App die Benutzung von nativen Nodejs-Modulen. Damit degradiert es Electron zu einem einfachen Browser-Fenster. Sodass der eigentliche Sinn von Electron zerstört wird.

Am Ende steht folgende Verzeichnisstruktur:

/
├── LICENSE
├── node_modules
├── package.json
├── src
│ ├── app.jsx
│ ├── index.html
│ └── index.js
└── yarn.lock

Wir werden unsere Änderungen ausschließlich in src machen werden.

Eine Demo-App

Unsere Beispielanwendung wird ein Nachbau der gtk3-demo-application.

gtk3-demo-application

Schließlich wollen wir ja eine Alternative zur GUI-Entwicklung finden.

Du findest den Source-Code für dieses Tutorial auf Github: https://github.com/rockiger/electron-react-example

Eine erste Änderung

Um zu sehen, ob das Hot-Reloading von Electron Forge funktioniert, werden wir eine kleine Änderung an unserer App vornehmen, bevor wir richtig loslegen.

Dafür öffnen wir die Datei app.jsx und ändern den Platzhaltertext ab.

...
<h2>Demo Application</h2>
...

Sobald du die Datei geändert hast und abspeicherst, sollte sich auch der angezeigte Text in der Electron App ändern.

Um aus der Kombination von Electron und React ein richtiges GUI framework zu machen, benötigen wir noch eine weitere Bibliothek: BlueprintJS.

BlueprintJS ist ein UI-Toolkit für React. Es bietet eine große Anzahl an Komponenten, aus denen wir unsere Oberfläche bauen können. Um BlueprintJS zu installieren, geben wir folgenden Code in der Kommandozeile ein:

npm i @blueprintjs/core --save

Danach müssen wir noch die CSS-Datein einbinden. Dazu öffnen wir index.html und fügen folgenden Code ein vor dem </head>-Tag ein:

  <link href="../node_modules/normalize.css/normalize.css" rel="stylesheet" />
  <link href="../node_modules/@blueprintjs/core/lib/css/blueprint.css" rel="stylesheet" />
  <link href="../node_modules/@blueprintjs/icons/lib/css/blueprint-icons.css" rel="stylesheet" />

Wenn du nach der Änderung die Electron neu lädst (<Strg>+R), solltest du eine andere Schriftart sehen.

Um unsere Demoanwendung nachzubauen, werden wir wie folgt vorgehen: Zuerst werden wir die Toolbar nachbauen, dann werden wir ein Textfeld integrieren und abschließend die Statuszeile implementieren.

Der Einfachheit halber werden wir alles in einer Datei entwickeln. Bei einer echten Anwendung würden wir aus Gründen der Übersichtlichkeit die Komponenten in mehrere Dateien aufspalten.

Toolbar

Die Toolbar-Komponente heißt in BlueprintJS Navbar. Sie hat mindestens eine NavbarGroup als Tochter. Diese wiederum kann Buttons und Trenner als Töchter haben.

Um die Demo Applikation nachzubilden haben wir der Navbar 5 Töchter gegeben. Davon sind 4 Buttonn und eine ein Trenner. Den Button mit dem Pfeil nach unten haben wir in ein Popover gepackt, um das Menü zu repräsentieren.

Der Code für unsere App sieht wie folgt aus:

import React from 'react';
import {
  Button,
  Classes,
  Navbar,
  NavbarDivider,
  NavbarGroup,
  Popover,
  Menu,
  MenuItem,
} from '@blueprintjs/core';

export default class App extends React.Component {
  render() {
    return (
      <div id="Layout">
        <Navbar>
          <NavbarGroup>
            <Button className={Classes.MINIMAL} icon="folder-open" />
            <Popover content={<Menu><MenuItem text="File 1" /></Menu>}>
              <Button className={Classes.MINIMAL} icon="chevron-down" />
            </Popover>
            <Button className={Classes.MINIMAL} icon="small-cross" />
            <NavbarDivider />
            <Button className={Classes.MINIMAL} icon="properties" />
          </NavbarGroup>
        </Navbar>
      </div>);
  }
}

Wir importieren zuerst die benötigten Module und erweitern dann die App-Komponente. Jede React Komponenten-Klasse benötigt eine Render-Methode. Das Besondere der Render-Methode ist, dass man dort HTML und Javascript mischen kann. (Es gibt auch noch andere Komponenten. Die Besprechung würde hier aber zu weit fühern. Ich verweise daher auf die React-Dokumentation.)

Um das Verhalten der Toolbar nachzubauen, müssen wir nun den einzelnen Buttons eine onclick-Funktion geben.

import { remote } from 'electron';
const showMessageBox = remote.dialog.showMessageBox;
const app = remote.app;
...
            <Popover content={
              <Menu>
                <MenuItem
                  text="File 1"
                  onClick={() => showMessageBox({
                    type: 'info',
                    message: 'You activated action: "file1"',
                    buttons: ['Close'],
                  })}
                />
              </Menu>}
            >
              <Button className={Classes.MINIMAL} icon="chevron-down" />
            </Popover>
            <Button
              className={Classes.MINIMAL}
              icon="small-cross"
              onClick={() => app.quit()}
            />
            <NavbarDivider />
            <Button
              className={Classes.MINIMAL}
              icon="properties"
              onClick={() => showMessageBox({
                type: 'info',
                message: 'You activated action: "logo"',
                buttons: ['Close'],
              })}
            />
...

Da Electron zwischen Haupt- und Render-Prozess unterscheidet, können wir aus einem Render-Prozess ( Das ist immer das, was als Fenster dargestellt wird.) auf den Hauptprozess nur zugreifen, wenn wir das Remote-Modul importieren.

Dies haben wir in den ersten drei Zeilen gemacht: Wir haben das Remote-Modul importiert und dann die Methode ShowMessageBox und das App-Objekt in zwei Konstanten gespeichert.

Die eigentlichen Click-Handler sind sehr einfach gehalten. Aus diesem werden nur die importierten Electron Methoden aufgerufen. Das Ordnersymbol hat übrigens keinen Click-Handler bekommen, weil dies in der Demo App auch so ist. Allerdings könnte es eine gute Übung sein, mit einem Klick auf das Ordnersymbol einen Öffnen-Dialog zu zeigen.

Fertige Toolbar

Textfeld

Als nächstes werden wir das Textfeld einfügen. Hier bedienen wir uns einer HTML-Textarea.

Es muss dazu gesagt werden, dass dies kein vollständiger Text-Editor ist. Eine Textarea hat nur eine eingeschränkte API. Es sind viele Bibliotheken auf dem Markt, um leistungsfähige Editoren in eine Website zu integrieren.

Bekannte Bibliotheken, die gut mit React funktionieren sind draft.js und slate.js. Laut diesem Github-Issue soll eine Lösung auf Basis von draft.js demnächst in Blueprint landen. Allerdings ist dieses Ticket schon relativ alt und ich weiß nicht, wann diese Lösung eingeführt wird.

Um unser Layout wie in der Demo-Application zu halten, müssen wir das CSS für das umschließende Element und den Editor ein wenig abändern. Wir nutzen Flexbox, damit das Textfeld den gesamten freien Raum des Fensters einnimmt.

...
<div id="Layout" style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
...
</Navbar>
<textarea
  id="TextField"
  style={{
    height: '100%',
    flexGrow: 1,
    overflow: 'auto',
    border: 'none',
    resize: 'none',
    outline: 'none',
  }}
/>
...

Statusbar

Abschließend erstellen wir noch unsere Statusbar. Diese stellt uns neben dem eigentlichen Layout, noch vor eine zweite Aufgabe: Wir müssen nämlich die Cursorposition und die Anzahl der Zeichen in der Statusbar anzeigen.

Das Layout ist schnell erstellt. Wir erstellen ein HTML Element, das eine Höhe von 50 Pixel hat und einen leicht grauen Hintergrund. Hierzu verwenden wir vordefinierte Farben von Blueprint und schreiben sie in das Style-Attribut der Statusbar.

...
  Colors,
} from '@blueprintjs/core';
...
<div
  id="StatusBar"
  style={{
    backgroundColor: Colors.LIGHT_GRAY5,
    borderTop: `1px solid ${Colors.LIGHT_GRAY1}`,
    height: '50px',
    padding: 12,
  }}
/>
</div>);
  }
}

Aufwändiger wird es nun, die Statistik über das Textdokument zu erstellen. Hierfür müssen wir Zustand in React einführen. Das Tolle an React ist, das bei Veränderungen des Zustands die betroffenen Komponenten aktualisiert werden. Das erlaubt es ein sehr simples Zustandsmodell der Applikation zu entwerfen. Wer noch gar keine Erfahrung mit React hat, sollte an dieser Stelle mit dem offiziellen Tutorial auseinandersetzen und dann hierher zurückkommen.

Als erstes führen wir eine Zustandsvariable statistic ein und initialisieren diese. Darüber hinaus wollen wir deren Inhalt in der Statusbar darstellen.

Als Erstes legen wir einen Konstruktor für unsere Komponente an, in der wir die Zustandsvariable definieren. Wo wir gerade im Konstruktor sind, binden wir noch eine Methode an das this-Objekt der Komponenten. Die Methode werden wir gleich erstellen.

...
export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      statistic: {
        row: 0,
        col: 0,
        chars: 0,
      },
    };
    this.onInput = this.onInput.bind(this);
  }
...

Als nächstes ergänzen wir das Textfeld um ein onKeyDown-Attribut. Damit wir Nutzer-Eingaben abfangen können. Um die Änderung der Textarea nun von unserer Statusbar darstellen zu können, fügen wir folgenden Text innerhalb des Elements ein.

...
<textarea
  id="TextField"
  style={{
    height: '100%',
    flexGrow: 1,
    overflow: 'auto',
    border: 'none',
    resize: 'none',
    outline: 'none',
  }}
  onKeyDown={this.onInput}
/>
...

Dabei erlaubt uns React mit den geschweiften Klammern direkt auf die Zustandsvariable der Komponente zuzugreifen. Bei jeder Änderung der Zustandsvariablen wird die Komponente aktualisiert.

<div
  id="StatusBar"
  style={{
    backgroundColor: Colors.LIGHT_GRAY5,
    borderTop: `1px solid ${Colors.LIGHT_GRAY1}`,
    height: '50px',
    padding: 12,
  }}
>
  Cursor at row {this.state.statistic.row} column  
  {this.state.statistic.col} - 
  {this.state.statistic.chars} chars in document
</div>

Zu guter Letzt schreiben wir noch eine einen Event-Handler für Nutzer-Eingaben. Dieser passt den Zustand der Komponente der aktuellen Cursorposition des Textfeldes an. Achtung: Der Event-Handler berücksichtigt nicht die typische Vorgehensweise in React. Er dient nur zur Veranschaulichung des reaktiven Charakters von React. Ich möchte an dieser Stelle nicht noch weitere React-Konzepte wie Referenzen oder Props einführen.

...
  onInput() {
    const textField = document.querySelector('#TextField');
    const textBeforCaret = textField.value.slice(0, textField.selectionStart);
    const rows = textBeforCaret.split('\n');
    const row = rows.length;
    const col = rows.pop().length;

    this.setState({ statistic: {
      row,
      col,
      chars: textField.value.length,
    } });
  }

  render() {
...

Wenn er nun unsere Anwendung anschauen ist diese der Beispielanwendung von GTK sehr ähnlich. 

Fertige Electron-React-Demo-Application

Im nächsten Teil, werden wir die Optik der App anpassen, um das Feeling der App noch “nativer” erscheinen zu lassen. Später werden wir noch das Menü entsprechend abändern, dass es die gleiche Funktionalität umfasst wie in der gtk3-demo-application.

Created with Dictandu

Akiee 0.0.4

Akiee Welcome-Screen

Ich habe Akiee Version 0.0.4 veröffentlicht. Dieses Release verbessert die User-Experience in einigen Details.

So wurden die Ansichten für den Source-Code der Markdown-Datei und für die Gesamtübersicht (Board-View) in das Menü verlegt, weil ich sie selbst kaum benutzt habe und sie aus meiner Sicht nicht so oft benutzt werden sollten.

Wiederholende Aufgaben werden nun wieder auf TODO gesetzt, wenn sie abgeschloßen wurden. Beendete Aufgaben bekommen ein Erledigungsdatum, damit man nachschauen kann, wann eine Aufgabe beendet wurde. Dies gilt auch für sich wiederholende Aufgaben, sie bekommen als Erledigungsdatum das Datum der letzten Erledigung.

In der DONE-Ansicht werden nun alle erledigten Aufgaben in chronologischer Folge angezeigt, da man so besser nachschauen kann, was man in letzter Zeit erledigt hat.

Um den Backlog besser zu ordnen, kann man nun einzelne Aufgaben an das Ende oder den Anfang verschieben.

Wer seine Aufgaben über Cloud-Storage-Dienste wie Dropbox, OwnCloud oder Syncthing abgleichen möchte, kann dies nun tun. Man wählt einfach ein synchronisiertes Verzeichnis als Ort zum Speichern der Aufgaben an.

Zusätzlich habe ich Akiee deutlich schneller gemacht. Zum einen läuft Akiee nun auf Electron und zum anderen wurde die Darstellung überarbeitet, damit sie schneller angezeigt wird. Dank Electron gibt es jetzt Downloads für jegliche erdenkliche Plattform und in jedem erdenklichen Paketformat.

Die User Storys für Akiee 0.0.3

  • Port from Node-Webkit to Electron.
  • As a (kanban) user I want to have the DONE state ordered by time in reverse, that I can see what I finished last.
  • When I am ordering my backlog, I want to put Tasks from the end of the backlog to the top.
  • Dropbox support.
  • Refactoring – Speedup
  • Move to electron for better toolkit and faster user interface.
  • Test Section aus dem Reagent Cookbook durcharbeiten und auf Akiee anwenden – Make Akiee ready for mobile.
  • Try to speed up akiee with cursors.
  • When I “done” a repeating task, I want that it is put to TODO again, but I want to see it in the DONE view.
  • Move Code-View and Board View to Menu, because it is almost never used.

Geplante Features

  • Mobile App to View task and add new ones.
  • Zim integration.
  • Markdown mode for zim.
  • When I enter a new task, I want to able to add more information to it without leaving my current view.
  • When I am scanning through a list in Akiee, I want to be able to use arrow-, page-, end- and pos1 keys.
  • When I am using Akiee a lot, I want to be able to donate somthing to the author, that I can help with / influence the development of Akiee.
  • When I am ordering my tasks, I want to be able to move them by drag&drap, because it is much faster, than using the arrow-buttons.
  • When I have larger tasks/stories (like writing a test article), I want to be able to divide it in sub-tasks.

Downloads

Releases für weitere Platformen findet ihr im Release-Repo auf GitHub.

Akiee 0.0.3 veroeffentlicht

Release 0.0.3 ist ein großer Schritt für Akiee. Ich habe Akiee von reinenm Javascript zu Clojurescript und Reagent, einem Wrapper für Facebook's React, migriert. Weiterhin wurde Akiee's Oberfläche überarbeitet, damit es sich besser in die unterstützten Desktopumgebungen einfügt. 

Auf funktionaler Ebene ist es jetzt möglich weitere Informationen zu einzelnen Aufgaben hinzuzufügen oder zu bearbeiten; wie z.B. geplanntes Datum, Wiederholungen, Tags, etc.

Die User Storys für Akiee 0.0.3 waren:

  • Merge rakiee repository with akiee
  • When I look over my task, I want to set/change an attribute so that I can change it to my needs.
  • improvement: Mac: Alias Ctrl shortcuts to Cmd
  • fix: Mac: Rename "node-webkit" in the menubar to Akiee
  • As A User I want to see the details of a task when I click on it, that I can see notes I did to finish it.
  • As a user, I want better integration, that the app feels more native to me.
  • As a developer I want to explore the options of using Clojurescript for Akiee, that I can leverage Lisp for competitive advantage

Um eine Kopie von Akiee zu bekommen, lade einen der folgenden Downloads herunter. Ich freue mich über jegliche Rückmeldungen.

Die nächsten Features

Was ist für Akiee 0.0.4. geplant?

  • As a (kanban) user I want to have the DONE state ordered by time in reverse, that I can see what I finished last.
  • When I make a mistake, I want to go back to the last state, so that I can start over.
  • As a User I want to order my task via Drag & Drop, that I can order my task more efficient.
  • When the markdown file of my tasks get to big, I want to export tasks that I done, so that I only have tasks in the file that are still relevant to me.
  • As a User I want to synchronize my tasks via Dropbox and similar services, that I can add tasks from every computer I have access to.
  • As a user I want to keep notes (not tasks), that I want to keep for future reference, that I can remember important information. 

Akiee 0.0.2

Als Erstes starte ich mit einem Bild. Oder, ladet euch die neueste Version einfach runter und seht selbst.

Akiee Version 0.0.2 mit Kanban-Board

Akiee ist schneller geworden und es sind einige Funktionen dazugekommen. Zusätzlich gab es noch ein paar Optimierungen.

Was ist neu?

  • Es gibt jetzt eine Suche, mit der man die aktuelle Ansicht filtern kann.
  • Die All-Ansicht wurde in Board umbenannt und entspricht jetzt einem einfachen Kanban-Board (siehe Screenshot). Mit dem Board kann man sich wunderbar einen Überblick über alle Task verschaffen und so besser priorisieren und planen.
  • In den einzelnen Tasks wird jetzt angezeigt, zu welchem Projekt sie gehören. Projekte sind im Editor nichts anderes als Überschriften erster Ordnung (#), die ihr ganz einfach hinzufügen könnt.
  • Der Willkommensbildschirm ist jetzt weniger verspielt, sondern erklärt Einsteigern ganz nüchtern, wie sie mit Akiee starten können.
  • Das Button-Layout wurde überarbeitet, der Editor hat ein Icon bekommen und ist jetzt nicht mehr auf einer Ebene mit dem Ansichten, sondern wurde zu den Funktionen auf die rechte Seite verschoben. Das ist aus meiner Sicht sinnvoller.
  • Die Startzeit wurde verringert, indem die Unit-Tests in der Produktivversion rausgenommen wurden.
  • Die Datenstrukturen und die Speicherung wurden refactored.
  • Mittlerweile werden auch Deadlines angezeigt; eingeben kann man sie allerdings nur, indem sie mit dem DEADLINE-Keyword im Editor eingibt: DEADLINE: <2013-8-24> einfach unter die Überschrift eines Tasks schreiben und die Deadline wird angezeigt.
  • Es gibt jetzt ein Waffle-Board zu Akiee, mit dem User-Storys geplant werden. Dort kann man sich die Reihenfolge der Features anschauen. Wenn ihr Featurewünsche habt, könnt ihr auf Github einen neue Issue anlegen oder kommentieren – ich freue mich über jede Anregung.

Was ist geplant?

Für die nächsten Versionen sind folgende Features geplant:

  • Umstieg auf Clojurescript und React, um nicht mehr mit Javascript arbeiten zu müssen.
  • Drag & Drop-Support, damit man effektiver die Reihenfolge der Aufgaben ändern kann.
  • Eine bessere Integration in die einzelnen Betriebssysteme, damit der Eindruck einer nativen App entsteht. Webei Gnome das wichtigste Zielsystem ist.
  • Die Done-Spalte soll nicht mehr nach RANK geordnet sein, damit man sehen kann, was man als letztes erledigt hat.
  • Eine Detailansicht der einzelnen Aufgaben, damit man Task auch ohne Markdown-Kenntnisse editieren kann.
  • Synchronisation mit Dropbox oder Ähnlichem
  • Notizenfunktion, weil Aufgaben und Notizen eng zusammenhängen.
  • Eine mobile Version
  • Ein Plugin-System
  • Pakete für Arch und Ubuntu

Weitere Features findet ihr auf dem Waffle-Board zu Akiee. Ich freue mich auf eure Kommentare und Anregungen.

Installation

Wer jetzt Lust bekommen hat Akiee auszuprobieren, findet hier den Akiee-Download.

Einfach das Archiv entpacken und entweder auf akiee (Linux) oder Akiee (Mac/Windows) klicken. Linux-Nutzer müssen eventuell noch festlegen, dass Skripte vom Dateimanager gestartet werden und nicht im Text-Editor geöffnet werden.

Nautilus configuration

Akiee ist in der Version 0.0.2; es ist das zweite Beta-Release. Ich selbst benutze Akiee aber schon seit einigen Monaten und würde mich freuen, wenn ihr eine Testfahrt mit Akiee macht.

Projektvorstellung: Akiee – eine neuartige Todo-Liste und Aufgabenverwaltung für Linux, Mac und Windows

Akiee ist eine Aufgabenverwaltung, die ich in den letzten Monaten geschrieben habe. Akiee ist der Versuch, das Thema Todo-Liste ein wenig anderes anzugehen.

Was unterscheidet Akiee von anderen Aufgabenverwaltungen:

  • Die Reihenfolge der Aufgaben soll einfach zu ändern sein. Mit Akiee kann man die Reihenfolge der Aufgaben ganz einfach per Mausklick ändern. Bei anderen Todo-Listen habe ich oft versucht, mit einer Mischung aus Prioritäten und Fälligkeiten meine Aufgaben zu sortieren. Mit Akiee weiß ich immer genau was als nächstes ansteht.

  • Akiee speichert meine Aufgaben in einer Markdown-Datei! Man kann seine Todo's mit jeden Texteditor auf diesen Planeten bearbeiten. Die Aufgaben werden nicht in einer Datenbank abgespeichert, die nur von Akiee gelesen werden kann. Wenn man seine Aufgabendatei mit seinem Dropbox-Ordner verlinkt, kann man auf seine Aufgaben ohne Probleme im Internet erreichen.

  • Aufgaben haben in Akiee drei Zustände: Todo, Doing, Done! Die Funktionsweise von Akiee ist an agile Methoden wie Kanban und Scrum angelehnt. Die Aufgaben haben deswegen drei Zustände: Todo – für alles was getan werden muss; DOING – für das was jetzt gerade getan wird; DONE – für die Dinge die schon erledigt wurden.

Akiee ist aus meiner Arbeit als Product Owner in einem Scrum-Team entstanden. Bevor ich Akiee hatte, habe ich den wunderbaren Org-Mode benutzt, von dem auch die Idee kam, Aufgaben in einer Datei zu speichern. Tatsächlich habe ich große Teile der Org-Mode-Syntax in Akiee eingebaut.

Technisch basiert Akiee auf Node-Webkit, die Oberfläche ist auf das Gnome3-Theme Adwaita zugeschnitten.

Video

Installation

Wer jetzt Lust bekommen hat Akiee mal auszuprobieren, kann das mit diesen Binarys tun:

Einfach das Archiv entpacken und entweder auf akiee (Linux) oder Akiee (Mac/Windows) klicken.

Akiee ist in der Version 0.0.1; es ist das erste Beta-Release. Ich selbst benutze Akiee aber schon seit einigen Monaten und würde mich freuen, wenn ihr eine Testfahrt mit Akiee wagt. Ich freue auf Anregungen und Fragen von euch. Die Sourcen findet ihr unter: https://github.com/rockiger/akiee

Wie man am besten Programmieren lernt

In diesem Artikel möchte ich die Erfahrungen und Fehler, die ich beim Programmierenlernen gemacht habe, teilen. Um eins von vornherein klarzustellen, ich bin kein top Programmierer, der in ein paar Nächten ein neues Betriebssystem zusammenhackt. Ich beherrsche ein wenig Webprogrammierung, kann Plugins und kleine GUIs schreiben. Als ich mit dem Programmieren angefangen habe, habe ich einige Fehler gemacht. Diese könnten für andere Programmieranfänger vielleicht interessant sein und können die vielen Expertentips ergänzen.

Meine Fehler

  1. C als erste Sprache

    Wie jeder Teenager wollte ich natürlich lernen wie man Spiele programmiert. Es wurde einem immer gesagt, dafür müsse man C lernen. Ich habs versucht und bin gescheitert. Punkt.

  2. Wing Commander als erstes Projekt 🙂

    Wie ich schon sagte, wollte ich Spiele programmieren, die ich selbst gespielt habe. Natürlich habe ich nie was zu Stande gebracht.

  3. Nicht gezielt genug

    Ich habe mich nie auf ein bestimmtes Projekt konzentriert. Ich habe mein Pläne, was ich als nächstes lernen sollte, immer geändert.

Was habe ich auf dem Weg gelernt?

  1. Lernt mit einer Skriptsprache programmieren!

    Ich kann jedem nur empfehlen mit einer Skriptsprache Programmieren zu lernen. Damit meine ich Python, Ruby, PHP, Perl und JavaScript. Der große Vorteil von Skriptsprachen sind unmittelbare Resultate, die einen weiter motiveren. Gebt print "Hello World" ein und ihr habt euer wichtiges Hello World Programm. Wenn man das mal mit Hello World in Java vergleicht: class HalloWorld { public static void main(String[] args) { String message="Hallo World!"; System.out.println(message); } } Java hat sogar die ganzen ergeizigen BWLer-Kommilitionen an meiner Uni zur verzweiflung gebracht. Ich persönlich empfehle Python als erste Programmiersprache. Python hat eine sehr klare Syntax und man kann eigentlich alles, von GUIs bis zu Webprogrammierung, mit Python machten. Wenn ihr euch auf Webprogrammierung konzentrieren wollt sind viellicht PHP oder JavaScript die bessere Wahl für euch (schneller erste Resultate). Später solltet ihr dann auch mal Scheme/Lisp lernen, es lehrt einen eine andere Denkweise und sollte euch zu einem besseren Programmierer machen. Deswegen wird es auch von vielen Einführungsbüchern an Universitäten verwendet. Danach solltet ihr, wenn ihr die wichtigesten Programmierkonzepte verstanden habt, auch noch C lernen. Denn C ist die Programmiersprache in der alle nennenswerten Betriebsysteme geschrieben sind und somit die Mutter aller Programmiersprachen.

  2. Arbeitet erstmal an kleinen Projekten.

    Das ist eigentlich selbstverständlich, aber ich hab mich nicht dran gehalten. Deswegen erwähne ich es hier trotzdem. Wenn ihr schnelle Resultate wollt, finde ich einfache Webprogrammierung ganz interessant und lohnend.

  3. Nur auf ein Projekt konzentrieren

    Fangt nicht mit mehrern Projekten gleichzeitig an. Das endet nur damit, dass ihr keins so richtig bearbeitet.

Ich hoffe meine Gedanken helfen euch auf eurem Weg Programmieren zu lernen und dabei motiviert zu bleiben. Falls jemand noch weitere Punkte hat oder anderer Meinung ist. Bitte teil dein Wissen mit mir.