Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Electron + WordPress =
Tomasz Dziuda
❤
Dlaczego?
Umiem w Electrony...
Źródło: https://getpublii.com
w WordPressy trochę też ...
coraz bardziej cenię swoją prywatność
Czego użyjemy?
Przyśpieszony Kurs Electrona
Źródło: https://atom.io/
Źródło: https://desktop.github.com/
=
Przyśpieszony Kurs Electrona
=
Przyśpieszony Kurs Electrona
= +
Przyśpieszony Kurs Electrona
= + +
Przyśpieszony Kurs Electrona
Przyśpieszony Kurs Electrona cz.2
Wątek główny
Przyśpieszony Kurs Electrona cz.2
Wątek główny
API systemu
Przyśpieszony Kurs Electrona cz.2
...
Wątki renderujące
Wątek główny
API systemu
Przyśpieszony Kurs Electrona cz.2
...
Wątki renderujące
Wątek główny
API systemu
IPC IPC IPC
Przyśpieszony Kurs Electrona cz.3
Build cross platform desktop apps with
JavaScript, HTML, and CSS
Przyśpieszony Kurs Electrona cz.3
Build cross platform desktop apps with
JavaScript, HTML, and CSS
XSS
Przyśpieszony Kurs Electrona cz.4
Brak możliwości ukrycia 

kodu źródłowego
Dlaczego WordPress?
Gotowe REST API
{REST API}
GET POST PUT DELETE
Gotowy panel zarządzania
Źródło: https://www.contentful.com/
Połowa pracy za nami a
jeszcze nie zaczęliśmy ;-)
1 WordPress = wiele aplikacji
Dlaczego React?
JSX
<App>
<Header />
<Content />
<Footer />
<Sidebar />
</App>
Ekosystem
Używają go w Automattic ;-)
Źródło: https://developer.wordpress.com/calypso/
Przydatne narzędzia
...mi pomogły ;-)
Postman
Źródło: https://www.getpostman.com/
Devtron
Źródło: https://electron.atom.io/devtron/
Założenia
WP Notes
WP Notes
• Synchronizacja notatek po uruchomieniu/zalogowaniu
• Obsługa wielu użytkowników
• Edytor Markdown
• Możliwość d...
WP Notes
• Synchronizacja notatek po uruchomieniu/zalogowaniu
• Obsługa wielu użytkowników
• Edytor Markdown
• Możliwość d...
WP Notes
• Synchronizacja notatek po uruchomieniu/zalogowaniu
• Obsługa wielu użytkowników
• Edytor Markdown
• Możliwość d...
WP Notes
• Synchronizacja notatek po uruchomieniu/zalogowaniu
• Obsługa wielu użytkowników
• Edytor Markdown
• Możliwość d...
WP Notes
• Synchronizacja notatek po uruchomieniu/zalogowaniu
• Obsługa wielu użytkowników
• Edytor Markdown
• Możliwość d...
Implementacja
Składowe
Składowe
Odpowiednie endpointy REST API Plugin + CPT
Składowe
Odpowiednie endpointy REST API
Autoryzacja komunikacji
Plugin + CPT
JWT
Składowe
Odpowiednie endpointy REST API
Autoryzacja komunikacji
Aplikacja napisana w Electronie
Plugin + CPT
JWT
Electron ...
Endpointy i CPT
Plugin dla aplikacji
Plugin dla aplikacji
• Tworzy dedykowany Custom Post Type dla danych
• Tworzy potrzebne endpointy
• Modyfikuje istniejące e...
Plugin dla aplikacji
• Tworzy dedykowany Custom Post Type dla danych
• Tworzy potrzebne endpointy
• Modyfikuje istniejące e...
Plugin dla aplikacji
• Tworzy dedykowany Custom Post Type dla danych
• Tworzy potrzebne endpointy
• Modyfikuje istniejące e...
Dlaczego Custom Post Type?
Dlaczego Custom Post Type?
• Możemy na jednym WordPressie oprzeć kilka
aplikacji
• CPT mogą mieć własne endpointy
• Możemy...
Dlaczego Custom Post Type?
• Możemy na jednym WordPressie oprzeć kilka
aplikacji
• CPT mogą mieć własne endpointy
• Możemy...
Dlaczego Custom Post Type?
• Możemy na jednym WordPressie oprzeć kilka
aplikacji
• CPT mogą mieć własne endpointy
• Możemy...
Endpointy
/wp-json/wp/v2/wp-notes
$args = array(
// ...
'show_in_rest' => true,
'rest_base' => 'wp-notes'
);
register_post_type( 'wp...
/wp-json/wp-notes/v1/notes?author=X
[
{
"id": 36,
"modificationDate": 1495370276000
},
...
{
"id": 13,
"modificationDate":...
Posty prywatne są przydatne ;)
Pobieranie prywatnych postów
1) Musimy być autoryzowani jako twórca wpisu
2) W URL-u REST API dodajemy:
wp-json/wp/v2/wp-n...
Pamiętajmy o strefach czasowych
CEST UTC
:-(
[
{
...
"date_gmt": "2017-05-21T12:37:56",
...
"modified_gmt": "2017-05-21T12:37:56",
...
}
]
new Date().getTime() // Zwra...
Modyfikacje endpointów
function dziudek_wp_notes_use_raw_content( $data, $post, $request ) {
$data->data['content']['plaintext'] = $post->post_co...
function dziudek_wp_notes_use_raw_content( $data, $post, $request ) {
$data->data['content']['plaintext'] = $post->post_co...
function dziudek_wp_notes_use_raw_content( $data, $post, $request ) {
$data->data['content']['plaintext'] = $post->post_co...
function dziudek_wp_notes_use_raw_content( $data, $post, $request ) {
$data->data['content']['plaintext'] = $post->post_co...
Autoryzacja
Źródło: https://jwt.io/
Źródło: https://jwt.io/
Dane w tokenie NIE SĄ
szyfrowane
Przy komunikacji z REST API
korzystaj z połączenia SSL
Źródło: https://pl.wordpress.org/plugins/jwt-authentication-for-wp-rest-api/
Gdy JWT nie działają dodaj w .htaccess:
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HT...
Autoryzacja - krok 1
Wysyłamy zapytaniem POST do endpointa /wp-json/jwt-auth/v1/token 

login i hasło użytkownika, którego...
Autoryzacja - krok 1
Wysyłamy zapytaniem POST do endpointa /wp-json/jwt-auth/v1/token 

login i hasło użytkownika, którego...
Autoryzacja - krok 2
Do każdego zapytania wymagającego 

autoryzacji dodajemy nagłówek:
Authorization: Bearer WARTOŚĆ_TOKE...
Aplikacja
Struktura aplikacji
<App>
Struktura aplikacji
<App>
<Editor><Sidebar>
Struktura aplikacji
<App>
<Editor><Sidebar>
<Search>
<List>
<ReactMarkdown>
Struktura aplikacji
<App>
<Editor><Sidebar>
<Search>
<List>
<Item>
<ReactMarkdown>
<Item>
<Item>
Komunikacja pomiędzy
komponentami
Wzorzec obserwatora
class EventEmitter extends React.Component {
dispatch(event, data) { ... }
subscribe(event, callback) ...
Wzorzec obserwatora
class EventEmitter extends React.Component {
dispatch(event, data) { ... }
subscribe(event, callback) ...
Wzorzec obserwatora
class EventEmitter extends React.Component {
dispatch(event, data) { ... }
subscribe(event, callback) ...
Wzorzec obserwatora
class EventEmitter extends React.Component {
dispatch(event, data) { ... }
subscribe(event, callback) ...
Wzorzec obserwatora
class EventEmitter extends React.Component {
dispatch(event, data) { ... }
subscribe(event, callback) ...
Wzorzec obserwatora
class EventEmitter extends React.Component {
dispatch(event, data) { ... }
subscribe(event, callback) ...
<App>
<Editor><Sidebar>
<Search>
<List>
<Item>
<ReactMarkdown>
<Item>
<Item>
<App>
<Editor><Sidebar>
<Search>
<List>
<Item>
<ReactMarkdown>
<Item>
<Item>
<App>
<Editor><Sidebar>
<Search>
<List>
<Item>
<ReactMarkdown>
<Item>
<Item>
subscribe('delete-item', callback)
<App>
<Editor><Sidebar>
<Search>
<List>
<Item>
<ReactMarkdown>
<Item>
<Item>
distpatch('delete-item', itemID)
Przechowywanie danych
Przechowywanie danych
user_ID_1
1.md
2.md
3.md
files.json
user_ID_2
4.md
5.md
files.json
Przechowywanie danych
user_ID_1
1.md
2.md
3.md
files.json
user_ID_2
4.md
5.md
files.json
[
{
id: 10,
title: "Post title",
modificationDate: 123049044
},
{
id: 10,
title: "Post title",
modificationDate: 123049044...
Synchronizacja danych
Pobranie danych z endpointa synchronizacji
dziudek-wp-notes/1/
1.md
2.md
3.md
files.json
[{
"id": 1,
"modificationDate": 10...
Porównanie dat modyfikacji postów
[{
"id": 1,
"modificationDate": 102
},

{
"id": 4,
"modificationDate": 105
}]
[{
"id": 1,...
Usunięcie nieistniejących plików
dziudek-wp-notes/1/
1.md
2.md
3.md
files.json
[{
"id": 1,
"modificationDate": 102
},

{
"i...
Pobranie i zaktualizowanie zmienionych wpisów
dziudek-wp-notes/1/
1.md
4.md
files.json
[{
"id": 1,
"modificationDate": 102
...
Zaktualizowanie pliku files.json
dziudek-wp-notes/1/
1.md
4.md
files.json
[{
"id": 1,
"modificationDate": 102
},

{
"id": 4,...
Pobieranie danych: node-fetch
Źródło: https://github.com/bitinn/node-fetch
Fetch API: https://developers.google.com/web/up...
Edytor
Źródło: https://github.com/JedWatson/react-md-editor
render: function() {
return <Editor
value={this.state.code}
op...
Źródło: https://codemirror.net/
Skróty klawiaturowe
import {remote} from 'electron';
const template = [{
label: "Edit",
submenu: [{
label: "Zapisz zmiany"...
DEMO
Co dalej?
Offline mode
Generowanie PDF-ów
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL('file://file-to-load.html')
win.webC...
Bezpieczne przechowywanie tokenów
node-keytar
Źródło: http://atom.github.io/node-keytar/
Natywny moduł do przechowywania haseł 

z użyciem Keychain (macOS),...
Do przejrzenia
• https://nodesource.com/blog/fifteen-essential-packages-to-get-started-with-electron/
• https://openfin.co/2...
Pytania?
tomasz@dziuda.com
@dziudek
http://dziudek.pl
http://www.slideshare.net/dziudek
Tomasz Dziuda
Electron + WordPress = ❤
Electron + WordPress = ❤
Upcoming SlideShare
Loading in …5
×

Electron + WordPress = ❤

3,981 views

Published on

Prezentacja o tym jak zgrać WordPressowe REST API z aplikacją desktopową opartą na Electronie

Published in: Internet
  • Be the first to comment

Electron + WordPress = ❤

  1. 1. Electron + WordPress = Tomasz Dziuda ❤
  2. 2. Dlaczego?
  3. 3. Umiem w Electrony... Źródło: https://getpublii.com
  4. 4. w WordPressy trochę też ...
  5. 5. coraz bardziej cenię swoją prywatność
  6. 6. Czego użyjemy?
  7. 7. Przyśpieszony Kurs Electrona
  8. 8. Źródło: https://atom.io/
  9. 9. Źródło: https://desktop.github.com/
  10. 10. = Przyśpieszony Kurs Electrona
  11. 11. = Przyśpieszony Kurs Electrona
  12. 12. = + Przyśpieszony Kurs Electrona
  13. 13. = + + Przyśpieszony Kurs Electrona
  14. 14. Przyśpieszony Kurs Electrona cz.2 Wątek główny
  15. 15. Przyśpieszony Kurs Electrona cz.2 Wątek główny API systemu
  16. 16. Przyśpieszony Kurs Electrona cz.2 ... Wątki renderujące Wątek główny API systemu
  17. 17. Przyśpieszony Kurs Electrona cz.2 ... Wątki renderujące Wątek główny API systemu IPC IPC IPC
  18. 18. Przyśpieszony Kurs Electrona cz.3 Build cross platform desktop apps with JavaScript, HTML, and CSS
  19. 19. Przyśpieszony Kurs Electrona cz.3 Build cross platform desktop apps with JavaScript, HTML, and CSS XSS
  20. 20. Przyśpieszony Kurs Electrona cz.4 Brak możliwości ukrycia 
 kodu źródłowego
  21. 21. Dlaczego WordPress?
  22. 22. Gotowe REST API {REST API} GET POST PUT DELETE
  23. 23. Gotowy panel zarządzania
  24. 24. Źródło: https://www.contentful.com/
  25. 25. Połowa pracy za nami a jeszcze nie zaczęliśmy ;-)
  26. 26. 1 WordPress = wiele aplikacji
  27. 27. Dlaczego React?
  28. 28. JSX <App> <Header /> <Content /> <Footer /> <Sidebar /> </App>
  29. 29. Ekosystem
  30. 30. Używają go w Automattic ;-) Źródło: https://developer.wordpress.com/calypso/
  31. 31. Przydatne narzędzia ...mi pomogły ;-)
  32. 32. Postman Źródło: https://www.getpostman.com/
  33. 33. Devtron Źródło: https://electron.atom.io/devtron/
  34. 34. Założenia
  35. 35. WP Notes
  36. 36. WP Notes • Synchronizacja notatek po uruchomieniu/zalogowaniu • Obsługa wielu użytkowników • Edytor Markdown • Możliwość dodawania, edycji i usuwania notatek • Wyszukiwarka notatek
  37. 37. WP Notes • Synchronizacja notatek po uruchomieniu/zalogowaniu • Obsługa wielu użytkowników • Edytor Markdown • Możliwość dodawania, edycji i usuwania notatek • Wyszukiwarka notatek
  38. 38. WP Notes • Synchronizacja notatek po uruchomieniu/zalogowaniu • Obsługa wielu użytkowników • Edytor Markdown • Możliwość dodawania, edycji i usuwania notatek • Wyszukiwarka notatek
  39. 39. WP Notes • Synchronizacja notatek po uruchomieniu/zalogowaniu • Obsługa wielu użytkowników • Edytor Markdown • Możliwość dodawania, edycji i usuwania notatek • Wyszukiwarka notatek
  40. 40. WP Notes • Synchronizacja notatek po uruchomieniu/zalogowaniu • Obsługa wielu użytkowników • Edytor Markdown • Możliwość dodawania, edycji i usuwania notatek • Wyszukiwarka notatek
  41. 41. Implementacja
  42. 42. Składowe
  43. 43. Składowe Odpowiednie endpointy REST API Plugin + CPT
  44. 44. Składowe Odpowiednie endpointy REST API Autoryzacja komunikacji Plugin + CPT JWT
  45. 45. Składowe Odpowiednie endpointy REST API Autoryzacja komunikacji Aplikacja napisana w Electronie Plugin + CPT JWT Electron + React
  46. 46. Endpointy i CPT
  47. 47. Plugin dla aplikacji
  48. 48. Plugin dla aplikacji • Tworzy dedykowany Custom Post Type dla danych • Tworzy potrzebne endpointy • Modyfikuje istniejące endpointy
  49. 49. Plugin dla aplikacji • Tworzy dedykowany Custom Post Type dla danych • Tworzy potrzebne endpointy • Modyfikuje istniejące endpointy
  50. 50. Plugin dla aplikacji • Tworzy dedykowany Custom Post Type dla danych • Tworzy potrzebne endpointy • Modyfikuje istniejące endpointy
  51. 51. Dlaczego Custom Post Type?
  52. 52. Dlaczego Custom Post Type? • Możemy na jednym WordPressie oprzeć kilka aplikacji • CPT mogą mieć własne endpointy • Możemy te endpointy bez obaw dostosować do swoich potrzeb
  53. 53. Dlaczego Custom Post Type? • Możemy na jednym WordPressie oprzeć kilka aplikacji • CPT mogą mieć własne endpointy • Możemy te endpointy bez obaw dostosować do swoich potrzeb
  54. 54. Dlaczego Custom Post Type? • Możemy na jednym WordPressie oprzeć kilka aplikacji • CPT mogą mieć własne endpointy • Możemy te endpointy bez obaw dostosować do swoich potrzeb
  55. 55. Endpointy
  56. 56. /wp-json/wp/v2/wp-notes $args = array( // ... 'show_in_rest' => true, 'rest_base' => 'wp-notes' ); register_post_type( 'wp_notes', $args );
  57. 57. /wp-json/wp-notes/v1/notes?author=X [ { "id": 36, "modificationDate": 1495370276000 }, ... { "id": 13, "modificationDate": 1495295589000 }, { "id": 9, "modificationDate": 1495368831000 } ] https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
  58. 58. Posty prywatne są przydatne ;)
  59. 59. Pobieranie prywatnych postów 1) Musimy być autoryzowani jako twórca wpisu 2) W URL-u REST API dodajemy: wp-json/wp/v2/wp-notes/?status=private
  60. 60. Pamiętajmy o strefach czasowych CEST UTC :-(
  61. 61. [ { ... "date_gmt": "2017-05-21T12:37:56", ... "modified_gmt": "2017-05-21T12:37:56", ... } ] new Date().getTime() // Zwraca czas UTC
  62. 62. Modyfikacje endpointów
  63. 63. function dziudek_wp_notes_use_raw_content( $data, $post, $request ) { $data->data['content']['plaintext'] = $post->post_content; $data->data['title']['plaintext'] = $post->post_title; $data->data['modified_gmt'] = strtotime($post->post_modified_gmt . ' UTC') * 1000; return $data; } add_filter( 'rest_prepare_wp_notes', 'dziudek_wp_notes_use_raw_content', 10, 3 );
  64. 64. function dziudek_wp_notes_use_raw_content( $data, $post, $request ) { $data->data['content']['plaintext'] = $post->post_content; $data->data['title']['plaintext'] = $post->post_title; $data->data['modified_gmt'] = strtotime($post->post_modified_gmt . ' UTC') * 1000; return $data; } add_filter( 'rest_prepare_wp_notes', 'dziudek_wp_notes_use_raw_content', 10, 3 );
  65. 65. function dziudek_wp_notes_use_raw_content( $data, $post, $request ) { $data->data['content']['plaintext'] = $post->post_content; $data->data['title']['plaintext'] = $post->post_title; $data->data['modified_gmt'] = strtotime($post->post_modified_gmt . ' UTC') * 1000; return $data; } add_filter( 'rest_prepare_wp_notes', 'dziudek_wp_notes_use_raw_content', 10, 3 );
  66. 66. function dziudek_wp_notes_use_raw_content( $data, $post, $request ) { $data->data['content']['plaintext'] = $post->post_content; $data->data['title']['plaintext'] = $post->post_title; $data->data['modified_gmt'] = strtotime($post->post_modified_gmt . ' UTC') * 1000; return $data; } add_filter( 'rest_prepare_wp_notes', 'dziudek_wp_notes_use_raw_content', 10, 3 );
  67. 67. Autoryzacja
  68. 68. Źródło: https://jwt.io/
  69. 69. Źródło: https://jwt.io/
  70. 70. Dane w tokenie NIE SĄ szyfrowane
  71. 71. Przy komunikacji z REST API korzystaj z połączenia SSL
  72. 72. Źródło: https://pl.wordpress.org/plugins/jwt-authentication-for-wp-rest-api/
  73. 73. Gdy JWT nie działają dodaj w .htaccess: RewriteEngine on RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1] Czasem może też być potrzebne dodanie: SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
  74. 74. Autoryzacja - krok 1 Wysyłamy zapytaniem POST do endpointa /wp-json/jwt-auth/v1/token 
 login i hasło użytkownika, którego chcemy autoryzować: { username: 'admin', password: 'password' }
  75. 75. Autoryzacja - krok 1 Wysyłamy zapytaniem POST do endpointa /wp-json/jwt-auth/v1/token 
 login i hasło użytkownika, którego chcemy autoryzować: { username: 'admin', password: 'password' } { "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ...", "user_display_name": "admin", "user_email": "admin@localhost.dev", "user_nicename": "admin" } Gdy dane są poprawne otrzymujemy token i dane użytkownika:
  76. 76. Autoryzacja - krok 2 Do każdego zapytania wymagającego 
 autoryzacji dodajemy nagłówek: Authorization: Bearer WARTOŚĆ_TOKENA
  77. 77. Aplikacja
  78. 78. Struktura aplikacji <App>
  79. 79. Struktura aplikacji <App> <Editor><Sidebar>
  80. 80. Struktura aplikacji <App> <Editor><Sidebar> <Search> <List> <ReactMarkdown>
  81. 81. Struktura aplikacji <App> <Editor><Sidebar> <Search> <List> <Item> <ReactMarkdown> <Item> <Item>
  82. 82. Komunikacja pomiędzy komponentami
  83. 83. Wzorzec obserwatora class EventEmitter extends React.Component { dispatch(event, data) { ... } subscribe(event, callback) { ... } unsubscribe(event, callback) { ... } }
  84. 84. Wzorzec obserwatora class EventEmitter extends React.Component { dispatch(event, data) { ... } subscribe(event, callback) { ... } unsubscribe(event, callback) { ... } }
  85. 85. Wzorzec obserwatora class EventEmitter extends React.Component { dispatch(event, data) { ... } subscribe(event, callback) { ... } unsubscribe(event, callback) { ... } }
  86. 86. Wzorzec obserwatora class EventEmitter extends React.Component { dispatch(event, data) { ... } subscribe(event, callback) { ... } unsubscribe(event, callback) { ... } }
  87. 87. Wzorzec obserwatora class EventEmitter extends React.Component { dispatch(event, data) { ... } subscribe(event, callback) { ... } unsubscribe(event, callback) { ... } } class App extends React.Component class App extends EventEmitter
  88. 88. Wzorzec obserwatora class EventEmitter extends React.Component { dispatch(event, data) { ... } subscribe(event, callback) { ... } unsubscribe(event, callback) { ... } } class App extends React.Component class App extends EventEmitter
  89. 89. <App> <Editor><Sidebar> <Search> <List> <Item> <ReactMarkdown> <Item> <Item>
  90. 90. <App> <Editor><Sidebar> <Search> <List> <Item> <ReactMarkdown> <Item> <Item>
  91. 91. <App> <Editor><Sidebar> <Search> <List> <Item> <ReactMarkdown> <Item> <Item> subscribe('delete-item', callback)
  92. 92. <App> <Editor><Sidebar> <Search> <List> <Item> <ReactMarkdown> <Item> <Item> distpatch('delete-item', itemID)
  93. 93. Przechowywanie danych
  94. 94. Przechowywanie danych user_ID_1 1.md 2.md 3.md files.json user_ID_2 4.md 5.md files.json
  95. 95. Przechowywanie danych user_ID_1 1.md 2.md 3.md files.json user_ID_2 4.md 5.md files.json
  96. 96. [ { id: 10, title: "Post title", modificationDate: 123049044 }, { id: 10, title: "Post title", modificationDate: 123049044 }, ... ] Przechowywanie danych files.jsonuser_ID_1 1.md 2.md 3.md files.json user_ID_2 4.md 5.md files.json
  97. 97. Synchronizacja danych
  98. 98. Pobranie danych z endpointa synchronizacji dziudek-wp-notes/1/ 1.md 2.md 3.md files.json [{ "id": 1, "modificationDate": 102 },
 { "id": 4, "modificationDate": 105 }] wp-json/wp-notes/v1/notes?author=1
  99. 99. Porównanie dat modyfikacji postów [{ "id": 1, "modificationDate": 102 },
 { "id": 4, "modificationDate": 105 }] [{ "id": 1, "modificationDate": 101 },
 { "id": 2, "modificationDate": 102 }, { "id": 3, "modificationDate": 103 }] Lokalnie Zdalnie
  100. 100. Usunięcie nieistniejących plików dziudek-wp-notes/1/ 1.md 2.md 3.md files.json [{ "id": 1, "modificationDate": 102 },
 { "id": 4, "modificationDate": 105 }]
  101. 101. Pobranie i zaktualizowanie zmienionych wpisów dziudek-wp-notes/1/ 1.md 4.md files.json [{ "id": 1, "modificationDate": 102 },
 { "id": 4, "modificationDate": 105 }]
  102. 102. Zaktualizowanie pliku files.json dziudek-wp-notes/1/ 1.md 4.md files.json [{ "id": 1, "modificationDate": 102 },
 { "id": 4, "modificationDate": 105 }]
  103. 103. Pobieranie danych: node-fetch Źródło: https://github.com/bitinn/node-fetch Fetch API: https://developers.google.com/web/updates/2015/03/introduction-to-fetch fetch('http://httpbin.org/post', { method: 'POST', 
 body: stream 
 }) .then(res => res.json()) .then(json => console.log(json));
  104. 104. Edytor Źródło: https://github.com/JedWatson/react-md-editor render: function() { return <Editor value={this.state.code} options={configObject} onChange={this.updateCode} /> }
  105. 105. Źródło: https://codemirror.net/
  106. 106. Skróty klawiaturowe import {remote} from 'electron'; const template = [{ label: "Edit", submenu: [{ label: "Zapisz zmiany", accelerator: "CmdOrCtrl+S", click: function() { // .. } ]} ]; const menu = remote.Menu.buildFromTemplate(template); remote.Menu.setApplicationMenu(menu);
  107. 107. DEMO
  108. 108. Co dalej?
  109. 109. Offline mode
  110. 110. Generowanie PDF-ów let win = new BrowserWindow({width: 800, height: 600}) win.loadURL('file://file-to-load.html') win.webContents.on('did-finish-load', () => { win.webContents.printToPDF({}, (error, data) => { fs.writeFile('/tmp/print.pdf', data, (error) => { console.log('Write PDF successfully.') }); }); });
  111. 111. Bezpieczne przechowywanie tokenów
  112. 112. node-keytar Źródło: http://atom.github.io/node-keytar/ Natywny moduł do przechowywania haseł 
 z użyciem Keychain (macOS), 
 Credential Vault (Windows) 
 i libsecret (Linux)
  113. 113. Do przejrzenia • https://nodesource.com/blog/fifteen-essential-packages-to-get-started-with-electron/ • https://openfin.co/2016/11/04/openfin-slashes-electron-memory-78/ • http://blog.atom.io/2017/04/18/improving-startup-time.html • https://openfin.co/2016/02/17/openfin-addressing-security-and-performance-challenges-with- electron/ • https://github.com/pojala/electrino • https://github.com/MacGapProject/MacGap1 Plugin: https://github.com/dziudek/WordCampPolska-WP-Notes-Plugin Aplikacja: https://github.com/dziudek/WordCampPolska-WP-Notes-App Artykuły warte uwagi:
  114. 114. Pytania?
  115. 115. tomasz@dziuda.com @dziudek http://dziudek.pl http://www.slideshare.net/dziudek Tomasz Dziuda

×