Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Realtime Cross Plattform Apps with Angular, ASP.NET Core and SignalR

Realtime Cross Plattform Apps with Angular, ASP.NET Core and SignalR

Fabian Gosebrink

February 16, 2021
Tweet

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. Realtim Cr
    Platfor App
    Angular, ASP.NET
    Cor & Signa R
    wit

    View Slide

  2. Fabian
    Gosebrink

    View Slide

  3. Realtim Cr
    Platfor App
    Angular, ASP.NET
    Cor & Signa R
    wit

    View Slide

  4. Server
    Clien

    View Slide

  5. Server
    Clien

    View Slide

  6. Server
    Clien
    HTTP WS

    View Slide

  7. View Slide

  8. Realtim
    Signa R
    wit

    View Slide

  9. Pollin

    View Slide

  10. Pollin

    View Slide

  11. Signa R

    View Slide

  12. Signa R
    WebSocket

    View Slide

  13. Signa R
    Server Sen Event

    View Slide

  14. Signa R
    Lon Pollin

    View Slide

  15. Signa R
    WebSocket
    Server Sen Event
    Lon Pollin

    View Slide

  16. namespace server
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    View Slide

  17. namespace server
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    5
    6
    7
    8
    9
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24

    View Slide

  18. namespace server
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    5
    6
    7
    8
    9
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    services.AddSignalR();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24

    View Slide

  19. namespace server
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    5
    6
    7
    8
    9
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    services.AddSignalR();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    View Slide

  20. namespace server
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    5
    6
    7
    8
    9
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    services.AddSignalR();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    app.UseRouting();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24

    View Slide

  21. namespace server
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    5
    6
    7
    8
    9
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    services.AddSignalR();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    app.UseRouting();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    17
    18
    19
    20
    21
    }
    22
    }
    23
    }
    24

    View Slide

  22. namespace server
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    services.AddSignalR();
    // ...
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    5
    6
    7
    8
    9
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    services.AddSignalR();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    public void Configure(/* ... */)
    {
    // ...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    }
    }
    }
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    app.UseRouting();
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    endpoints.MapHub("/todohub");
    20
    });
    21
    }
    22
    }
    23
    }
    24
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    endpoints.MapHub("/todohub");
    });
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    17
    18
    19
    20
    21
    }
    22
    }
    23
    }
    24
    endpoints.MapHub("/todohub");
    namespace server
    1
    {
    2
    public class Startup
    3
    {
    4
    public void ConfigureServices(IServiceCollection services)
    5
    {
    6
    // ...
    7
    services.AddSignalR();
    8
    // ...
    9
    }
    10
    11
    public void Configure(/* ... */)
    12
    {
    13
    // ...
    14
    app.UseRouting();
    15
    16
    app.UseEndpoints(endpoints =>
    17
    {
    18
    endpoints.MapControllers();
    19
    20
    });
    21
    }
    22
    }
    23
    }
    24

    View Slide

  23. Hub

    View Slide

  24. Hub
    namespace server.Hubs
    {
    public class TodoHub : Hub
    {
    public async Task MySuperDuperAction(object data)
    {
    await Clients.All.SendAsync("myclientmethod", data);
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    View Slide

  25. public class TodosController : ControllerBase
    {
    private readonly IHubContext _todoHubContext;
    public TodosController(
    IHubContext todoHubContext
    )
    {
    _todoHubContext = todoHubContext;
    }
    [HttpPost(Name = nameof(AddTodo))]
    public async Task AddTodo(
    [FromBody] TodoCreateDto todoCreateDto)
    {
    // ... do http things
    await _todoHubContext.Clients.All.SendAsync("todo-added", newTodoEntity);
    return CreatedAtRoute(/* ... */);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    View Slide

  26. View Slide

  27. View Slide

  28. View Slide

  29. @microsoft/signalr

    View Slide

  30. View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. Dem

    View Slide

  36. Cr Platfor

    View Slide

  37. Ma

    View Slide

  38. Ma
    Window

    View Slide

  39. Ma
    Window
    Lin

    View Slide

  40. Mobil

    View Slide

  41. Mobil
    Desktop

    View Slide

  42. Mobil
    Desktop
    Web

    View Slide

  43. s
    muc
    mor ...

    View Slide

  44. Cordov

    View Slide

  45. Apache Cordova is an open-
    source mobile development
    framework. It allows you to use
    standard web technologies -
    HTML5, CSS3, and JavaScript for
    cross-platform development.
    "
    "

    View Slide

  46. View Slide

  47. $ npm install cordova -g

    View Slide

  48. $ cordova create myFirstApp

    View Slide

  49. ├── www
    │ ├── css
    │ │ └── index.css
    │ ├── img
    │ │ └── logo.png
    │ ├── js
    │ │ └── index.js
    │ └── index.html
    ├── .gitignore
    ├── config.xml
    └── package.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    View Slide

  50. ├── www
    │ ├── css
    │ │ └── index.css
    │ ├── img
    │ │ └── logo.png
    │ ├── js
    │ │ └── index.js
    │ └── index.html
    ├── .gitignore
    ├── config.xml
    └── package.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ├── www
    1
    │ ├── css
    2
    │ │ └── index.css
    3
    │ ├── img
    4
    │ │ └── logo.png
    5
    │ ├── js
    6
    │ │ └── index.js
    7
    │ └── index.html
    8
    ├── .gitignore
    9
    ├── config.xml
    10
    └── package.json
    11

    View Slide

  51. ├── www
    │ ├── css
    │ │ └── index.css
    │ ├── img
    │ │ └── logo.png
    │ ├── js
    │ │ └── index.js
    │ └── index.html
    ├── .gitignore
    ├── config.xml
    └── package.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ├── www
    1
    │ ├── css
    2
    │ │ └── index.css
    3
    │ ├── img
    4
    │ │ └── logo.png
    5
    │ ├── js
    6
    │ │ └── index.js
    7
    │ └── index.html
    8
    ├── .gitignore
    9
    ├── config.xml
    10
    └── package.json
    11
    │ ├── css
    │ │ └── index.css
    │ ├── img
    │ │ └── logo.png
    │ ├── js
    │ │ └── index.js
    │ └── index.html
    ├── www
    1
    2
    3
    4
    5
    6
    7
    8
    ├── .gitignore
    9
    ├── config.xml
    10
    └── package.json
    11

    View Slide

  52. ├── www
    │ ├── css
    │ │ └── index.css
    │ ├── img
    │ │ └── logo.png
    │ ├── js
    │ │ └── index.js
    │ └── index.html
    ├── .gitignore
    ├── config.xml
    └── package.json
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ├── www
    1
    │ ├── css
    2
    │ │ └── index.css
    3
    │ ├── img
    4
    │ │ └── logo.png
    5
    │ ├── js
    6
    │ │ └── index.js
    7
    │ └── index.html
    8
    ├── .gitignore
    9
    ├── config.xml
    10
    └── package.json
    11
    │ ├── css
    │ │ └── index.css
    │ ├── img
    │ │ └── logo.png
    │ ├── js
    │ │ └── index.js
    │ └── index.html
    ├── www
    1
    2
    3
    4
    5
    6
    7
    8
    ├── .gitignore
    9
    ├── config.xml
    10
    └── package.json
    11
    ├── config.xml
    ├── www
    1
    │ ├── css
    2
    │ │ └── index.css
    3
    │ ├── img
    4
    │ │ └── logo.png
    5
    │ ├── js
    6
    │ │ └── index.js
    7
    │ └── index.html
    8
    ├── .gitignore
    9
    10
    └── package.json
    11

    View Slide



  53. Gatherr
    Gatherr - Demo Application

    Offering Solutions Software























    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    View Slide

  54. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29

    View Slide

  55. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9
    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29

    View Slide

  56. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9
    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29







    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11
    12
    13
    14
    15
    16
    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29

    View Slide

  57. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9
    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29







    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11
    12
    13
    14
    15
    16
    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29



    g p g
    Offering Solutions Software
    6

    7

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18
    19
    20
    21
    22

    23
    24

    25
    26

    27

    28

    29

    30

    31

    32
    33

    34

    View Slide

  58. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9
    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29







    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11
    12
    13
    14
    15
    16
    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29




    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18
    19
    20
    21
    22

    23
    24

    25
    26

    27

    28

    29


    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22
    23
    24

    25
    26

    27

    28

    29

    30

    31

    32
    33

    34

    35

    36

    View Slide

  59. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9
    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29







    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11
    12
    13
    14
    15
    16
    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29




    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18
    19
    20
    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22
    23
    24

    25
    26

    27

    28

    29


    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24
    25
    26

    27

    28

    29

    30

    31

    32
    33

    34

    35

    36

    View Slide

  60. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9
    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29







    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11
    12
    13
    14
    15
    16
    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29




    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18
    19
    20
    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22
    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24
    25
    26

    27

    28

    29







    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26
    27
    28
    29
    30
    31
    32
    33

    34

    35

    36

    View Slide

  61. Gatherr
    Gatherr - Demo Application


    1

    2
    3
    4
    5
    6
    7
    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9
    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29







    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11
    12
    13
    14
    15
    16
    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29




    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18
    19
    20
    21
    22

    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22
    23
    24

    25
    26

    27

    28

    29


    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24
    25
    26

    27

    28

    29




    1

    2
    Gatherr
    3
    Gatherr - Demo Application
    4

    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26
    27
    28
    29



    8
    9

    10
    11

    12

    13

    14

    15

    16

    17
    18

    19

    20

    21
    22

    23
    24

    25
    26

    27

    28

    29

    30

    31

    32
    33
    34
    35

    36

    View Slide

  62. $ cordova plugin add cordova-plugin-camera

    View Slide

  63. cordova platform add android
    cordova platform add ios
    cordova build
    1
    2
    3
    4

    View Slide

  64. cordova platform add android
    cordova platform add ios
    cordova build
    1
    2
    3
    4
    cordova platform add android
    1
    cordova platform add ios
    2
    3
    cordova build
    4

    View Slide

  65. cordova platform add android
    cordova platform add ios
    cordova build
    1
    2
    3
    4
    cordova platform add android
    1
    cordova platform add ios
    2
    3
    cordova build
    4
    cordova platform add ios
    cordova platform add android
    1
    2
    3
    cordova build
    4

    View Slide

  66. cordova platform add android
    cordova platform add ios
    cordova build
    1
    2
    3
    4
    cordova platform add android
    1
    cordova platform add ios
    2
    3
    cordova build
    4
    cordova platform add ios
    cordova platform add android
    1
    2
    3
    cordova build
    4 cordova build
    cordova platform add android
    1
    cordova platform add ios
    2
    3
    4

    View Slide

  67. View Slide

  68. View Slide

  69. View Slide

  70. View Slide

  71. View Slide

  72. Dem

    View Slide

  73. Electro

    View Slide

  74. Electron is a tool for building Cross-
    Platform Desktop Apps with
    Javascript, Html and CSS
    "
    "

    View Slide

  75. View Slide

  76. View Slide

  77. Chromiu

    View Slide

  78. View Slide

  79. View Slide

  80. an man mor ...

    View Slide

  81. $ npm install electron -g

    View Slide

  82. ├── index.html
    ├── index.js
    └── package.json

    View Slide

  83. {
    "name": "your-app",
    "version": "0.1.0",
    "main": "index.js",
    "scripts": {
    "start": "electron ."
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8

    View Slide

  84. {
    "name": "your-app",
    "version": "0.1.0",
    "main": "index.js",
    "scripts": {
    "start": "electron ."
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    "main": "index.js",
    {
    1
    "name": "your-app",
    2
    "version": "0.1.0",
    3
    4
    "scripts": {
    5
    "start": "electron ."
    6
    }
    7
    }
    8

    View Slide

  85. const { app, BrowserWindow } = require('electron');
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    app.whenReady().then(createWindow);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    View Slide

  86. const { app, BrowserWindow } = require('electron');
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    app.whenReady().then(createWindow);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17

    View Slide

  87. const { app, BrowserWindow } = require('electron');
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    app.whenReady().then(createWindow);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    const { app, BrowserWindow } = require('electron');
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    app.whenReady().then(createWindow);
    17

    View Slide

  88. const { app, BrowserWindow } = require('electron');
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    app.whenReady().then(createWindow);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    const { app, BrowserWindow } = require('electron');
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    app.whenReady().then(createWindow);
    17
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17

    View Slide

  89. const { app, BrowserWindow } = require('electron');
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    app.whenReady().then(createWindow);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    const { app, BrowserWindow } = require('electron');
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    app.whenReady().then(createWindow);
    17
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17
    win.loadFile('index.html');
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17

    View Slide

  90. const { app, BrowserWindow } = require('electron');
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    app.whenReady().then(createWindow);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17
    createWindow = () => {
    // Create the browser window.
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    // and load the index.html of the app.
    win.loadFile('index.html');
    };
    const { app, BrowserWindow } = require('electron');
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    app.whenReady().then(createWindow);
    17
    const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true,
    },
    });
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17
    win.loadFile('index.html');
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    14
    };
    15
    16
    app.whenReady().then(createWindow);
    17 app.whenReady().then(createWindow);
    const { app, BrowserWindow } = require('electron');
    1
    2
    createWindow = () => {
    3
    // Create the browser window.
    4
    const win = new BrowserWindow({
    5
    width: 800,
    6
    height: 600,
    7
    webPreferences: {
    8
    nodeIntegration: true,
    9
    },
    10
    });
    11
    12
    // and load the index.html of the app.
    13
    win.loadFile('index.html');
    14
    };
    15
    16
    17

    View Slide





  91. Hello World!


    Hello World!


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    View Slide

  92. $ electron .

    View Slide

  93. View Slide

  94. View Slide

  95. Process
    Mai

    View Slide

  96. Process
    Renderer

    View Slide

  97. View Slide

  98. View Slide

  99. View Slide

  100. ├── assets
    │ ...
    ├── 6.2c6c97b8608a85a82adc.js
    ├── common.42c8477e0640407ae045.js
    ├── favicon.ico
    ├── icon.ico
    ├── index.html
    ├── index.js
    ├── main.8bb24261aa275d6a43db.js
    ├── package.json
    ├── polyfills-es5.739d51467cc1d8efbfae.js
    ├── polyfills.ef4ae634e106e395892c.js
    ├── runtime.061b6e0597d9fe17b937.js
    ├── scripts.82aad45f2fad02beee3c.js
    ├── styles.f503a9ab21b5d570c8af.css
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    View Slide

  101. ├── assets
    │ ...
    ├── 6.2c6c97b8608a85a82adc.js
    ├── common.42c8477e0640407ae045.js
    ├── favicon.ico
    ├── icon.ico
    ├── index.html
    ├── index.js
    ├── main.8bb24261aa275d6a43db.js
    ├── package.json
    ├── polyfills-es5.739d51467cc1d8efbfae.js
    ├── polyfills.ef4ae634e106e395892c.js
    ├── runtime.061b6e0597d9fe17b937.js
    ├── scripts.82aad45f2fad02beee3c.js
    ├── styles.f503a9ab21b5d570c8af.css
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ├── assets
    │ ...
    ├── 6.2c6c97b8608a85a82adc.js
    ├── common.42c8477e0640407ae045.js
    ├── favicon.ico
    ├── index.html
    ├── main.8bb24261aa275d6a43db.js
    ├── polyfills-es5.739d51467cc1d8efbfae.js
    ├── polyfills.ef4ae634e106e395892c.js
    ├── runtime.061b6e0597d9fe17b937.js
    ├── scripts.82aad45f2fad02beee3c.js
    ├── styles.f503a9ab21b5d570c8af.css
    1
    2
    3
    4
    5
    ├── icon.ico
    6
    7
    ├── index.js
    8
    9
    ├── package.json
    10
    11
    12
    13
    14
    15

    View Slide

  102. ├── assets
    │ ...
    ├── 6.2c6c97b8608a85a82adc.js
    ├── common.42c8477e0640407ae045.js
    ├── favicon.ico
    ├── icon.ico
    ├── index.html
    ├── index.js
    ├── main.8bb24261aa275d6a43db.js
    ├── package.json
    ├── polyfills-es5.739d51467cc1d8efbfae.js
    ├── polyfills.ef4ae634e106e395892c.js
    ├── runtime.061b6e0597d9fe17b937.js
    ├── scripts.82aad45f2fad02beee3c.js
    ├── styles.f503a9ab21b5d570c8af.css
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ├── assets
    │ ...
    ├── 6.2c6c97b8608a85a82adc.js
    ├── common.42c8477e0640407ae045.js
    ├── favicon.ico
    ├── index.html
    ├── main.8bb24261aa275d6a43db.js
    ├── polyfills-es5.739d51467cc1d8efbfae.js
    ├── polyfills.ef4ae634e106e395892c.js
    ├── runtime.061b6e0597d9fe17b937.js
    ├── scripts.82aad45f2fad02beee3c.js
    ├── styles.f503a9ab21b5d570c8af.css
    1
    2
    3
    4
    5
    ├── icon.ico
    6
    7
    ├── index.js
    8
    9
    ├── package.json
    10
    11
    12
    13
    14
    15
    ├── icon.ico
    ├── index.js
    ├── package.json
    ├── assets
    1
    │ ...
    2
    ├── 6.2c6c97b8608a85a82adc.js
    3
    ├── common.42c8477e0640407ae045.js
    4
    ├── favicon.ico
    5
    6
    ├── index.html
    7
    8
    ├── main.8bb24261aa275d6a43db.js
    9
    10
    ├── polyfills-es5.739d51467cc1d8efbfae.js
    11
    ├── polyfills.ef4ae634e106e395892c.js
    12
    ├── runtime.061b6e0597d9fe17b937.js
    13
    ├── scripts.82aad45f2fad02beee3c.js
    14
    ├── styles.f503a9ab21b5d570c8af.css
    15

    View Slide

  103. View Slide

  104. Communicatio

    View Slide

  105. Communicatio
    IPC

    View Slide

  106. mai proces
    const { ipcMain } = require('electron')
    ipcMain.on('asynchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.reply('asynchronous-reply', 'pong')
    })
    ipcMain.on('synchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.returnValue = 'pong'
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    View Slide

  107. mai proces
    const { ipcMain } = require('electron')
    ipcMain.on('asynchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.reply('asynchronous-reply', 'pong')
    })
    ipcMain.on('synchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.returnValue = 'pong'
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const { ipcMain } = require('electron')
    1
    2
    ipcMain.on('asynchronous-message', (event, arg) => {
    3
    console.log(arg) // prints "ping"
    4
    event.reply('asynchronous-reply', 'pong')
    5
    })
    6
    7
    ipcMain.on('synchronous-message', (event, arg) => {
    8
    console.log(arg) // prints "ping"
    9
    event.returnValue = 'pong'
    10
    })
    11

    View Slide

  108. mai proces
    const { ipcMain } = require('electron')
    ipcMain.on('asynchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.reply('asynchronous-reply', 'pong')
    })
    ipcMain.on('synchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.returnValue = 'pong'
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const { ipcMain } = require('electron')
    1
    2
    ipcMain.on('asynchronous-message', (event, arg) => {
    3
    console.log(arg) // prints "ping"
    4
    event.reply('asynchronous-reply', 'pong')
    5
    })
    6
    7
    ipcMain.on('synchronous-message', (event, arg) => {
    8
    console.log(arg) // prints "ping"
    9
    event.returnValue = 'pong'
    10
    })
    11
    ipcMain.on('asynchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.reply('asynchronous-reply', 'pong')
    })
    const { ipcMain } = require('electron')
    1
    2
    3
    4
    5
    6
    7
    ipcMain.on('synchronous-message', (event, arg) => {
    8
    console.log(arg) // prints "ping"
    9
    event.returnValue = 'pong'
    10
    })
    11

    View Slide

  109. mai proces
    const { ipcMain } = require('electron')
    ipcMain.on('asynchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.reply('asynchronous-reply', 'pong')
    })
    ipcMain.on('synchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.returnValue = 'pong'
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const { ipcMain } = require('electron')
    1
    2
    ipcMain.on('asynchronous-message', (event, arg) => {
    3
    console.log(arg) // prints "ping"
    4
    event.reply('asynchronous-reply', 'pong')
    5
    })
    6
    7
    ipcMain.on('synchronous-message', (event, arg) => {
    8
    console.log(arg) // prints "ping"
    9
    event.returnValue = 'pong'
    10
    })
    11
    ipcMain.on('asynchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.reply('asynchronous-reply', 'pong')
    })
    const { ipcMain } = require('electron')
    1
    2
    3
    4
    5
    6
    7
    ipcMain.on('synchronous-message', (event, arg) => {
    8
    console.log(arg) // prints "ping"
    9
    event.returnValue = 'pong'
    10
    })
    11
    ipcMain.on('synchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
    event.returnValue = 'pong'
    })
    const { ipcMain } = require('electron')
    1
    2
    ipcMain.on('asynchronous-message', (event, arg) => {
    3
    console.log(arg) // prints "ping"
    4
    event.reply('asynchronous-reply', 'pong')
    5
    })
    6
    7
    8
    9
    10
    11

    View Slide

  110. renderer proces
    const { ipcRenderer } = require('electron');
    // prints "pong"
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    console.log(arg) // prints "pong"
    })
    ipcRenderer.send('asynchronous-message', 'ping')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    View Slide

  111. renderer proces
    const { ipcRenderer } = require('electron');
    // prints "pong"
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    console.log(arg) // prints "pong"
    })
    ipcRenderer.send('asynchronous-message', 'ping')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const { ipcRenderer } = require('electron');
    1
    2
    // prints "pong"
    3
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    4
    5
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    6
    console.log(arg) // prints "pong"
    7
    })
    8
    9
    ipcRenderer.send('asynchronous-message', 'ping')
    10

    View Slide

  112. renderer proces
    const { ipcRenderer } = require('electron');
    // prints "pong"
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    console.log(arg) // prints "pong"
    })
    ipcRenderer.send('asynchronous-message', 'ping')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const { ipcRenderer } = require('electron');
    1
    2
    // prints "pong"
    3
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    4
    5
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    6
    console.log(arg) // prints "pong"
    7
    })
    8
    9
    ipcRenderer.send('asynchronous-message', 'ping')
    10
    // prints "pong"
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    const { ipcRenderer } = require('electron');
    1
    2
    3
    4
    5
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    6
    console.log(arg) // prints "pong"
    7
    })
    8
    9
    ipcRenderer.send('asynchronous-message', 'ping')
    10

    View Slide

  113. renderer proces
    const { ipcRenderer } = require('electron');
    // prints "pong"
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    console.log(arg) // prints "pong"
    })
    ipcRenderer.send('asynchronous-message', 'ping')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const { ipcRenderer } = require('electron');
    1
    2
    // prints "pong"
    3
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    4
    5
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    6
    console.log(arg) // prints "pong"
    7
    })
    8
    9
    ipcRenderer.send('asynchronous-message', 'ping')
    10
    // prints "pong"
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    const { ipcRenderer } = require('electron');
    1
    2
    3
    4
    5
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    6
    console.log(arg) // prints "pong"
    7
    })
    8
    9
    ipcRenderer.send('asynchronous-message', 'ping')
    10
    ipcRenderer.on('asynchronous-reply', (event, arg) => {
    console.log(arg) // prints "pong"
    })
    ipcRenderer.send('asynchronous-message', 'ping')
    const { ipcRenderer } = require('electron');
    1
    2
    // prints "pong"
    3
    console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
    4
    5
    6
    7
    8
    9
    10

    View Slide

  114. mai proces
    var os = require('os');
    var cpus = os.cpus();
    1
    2
    3

    View Slide

  115. mai proces
    var os = require('os');
    var cpus = os.cpus();
    1
    2
    3
    var os = require('os');
    1
    2
    var cpus = os.cpus();
    3

    View Slide

  116. mai proces
    var os = require('os');
    var cpus = os.cpus();
    1
    2
    3
    var os = require('os');
    1
    2
    var cpus = os.cpus();
    3 var cpus = os.cpus();
    var os = require('os');
    1
    2
    3

    View Slide

  117. mai proces
    let startSendCpuValues = () => {
    setInterval(() => {
    cpuValues.getCPUUsage(percentage => {
    if (mainWindow) {
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    }
    });
    }, 1000);
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    View Slide

  118. mai proces
    let startSendCpuValues = () => {
    setInterval(() => {
    cpuValues.getCPUUsage(percentage => {
    if (mainWindow) {
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    }
    });
    }, 1000);
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let startSendCpuValues = () => {
    setInterval(() => {
    cpuValues.getCPUUsage(percentage => {
    if (mainWindow) {
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    }
    });
    }, 1000);
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    View Slide

  119. mai proces
    let startSendCpuValues = () => {
    setInterval(() => {
    cpuValues.getCPUUsage(percentage => {
    if (mainWindow) {
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    }
    });
    }, 1000);
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let startSendCpuValues = () => {
    setInterval(() => {
    cpuValues.getCPUUsage(percentage => {
    if (mainWindow) {
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    }
    });
    }, 1000);
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    cpuValues.getCPUUsage(percentage => {
    });
    let startSendCpuValues = () => {
    1
    setInterval(() => {
    2
    3
    if (mainWindow) {
    4
    mainWindow.webContents.send(
    5
    'newCpuValue',
    6
    (percentage * 100).toFixed(2)
    7
    );
    8
    }
    9
    10
    }, 1000);
    11
    };
    12

    View Slide

  120. mai proces
    let startSendCpuValues = () => {
    setInterval(() => {
    cpuValues.getCPUUsage(percentage => {
    if (mainWindow) {
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    }
    });
    }, 1000);
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let startSendCpuValues = () => {
    setInterval(() => {
    cpuValues.getCPUUsage(percentage => {
    if (mainWindow) {
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    }
    });
    }, 1000);
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    cpuValues.getCPUUsage(percentage => {
    });
    let startSendCpuValues = () => {
    1
    setInterval(() => {
    2
    3
    if (mainWindow) {
    4
    mainWindow.webContents.send(
    5
    'newCpuValue',
    6
    (percentage * 100).toFixed(2)
    7
    );
    8
    }
    9
    10
    }, 1000);
    11
    };
    12
    mainWindow.webContents.send(
    'newCpuValue',
    (percentage * 100).toFixed(2)
    );
    let startSendCpuValues = () => {
    1
    setInterval(() => {
    2
    cpuValues.getCPUUsage(percentage => {
    3
    if (mainWindow) {
    4
    5
    6
    7
    8
    }
    9
    });
    10
    }, 1000);
    11
    };
    12

    View Slide

  121. renderer proces
    @Injectable({ providedIn: 'root' })
    export class CpuValueService {
    private onNewCpuValue = new Subject();
    get newCpuValue(){
    return this.onNewCpuValue.asObservable();
    }
    constructor(private electronService: ElectronService) {
    if (environment.desktop) {
    this.registerCpuEvent();
    }
    }
    private registerCpuEvent() {
    if (this.electronService.ipcRenderer) {
    this.electronService.ipcRenderer.on(
    'newCpuValue',
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    View Slide

  122. renderer proces
    @Injectable({ providedIn: 'root' })
    export class CpuValueService {
    private onNewCpuValue = new Subject();
    get newCpuValue(){
    return this.onNewCpuValue.asObservable();
    }
    constructor(private electronService: ElectronService) {
    if (environment.desktop) {
    this.registerCpuEvent();
    }
    }
    private registerCpuEvent() {
    if (this.electronService.ipcRenderer) {
    this.electronService.ipcRenderer.on(
    'newCpuValue',
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    constructor(private electronService: ElectronService) {
    if (environment.desktop) {
    this.registerCpuEvent();
    }
    }
    @Injectable({ providedIn: root })
    1
    export class CpuValueService {
    2
    private onNewCpuValue = new Subject();
    3
    4
    get newCpuValue(){
    5
    return this.onNewCpuValue.asObservable();
    6
    }
    7
    8
    9
    10
    11
    12
    13
    14
    private registerCpuEvent() {
    15
    if (this.electronService.ipcRenderer) {
    16
    this.electronService.ipcRenderer.on(
    17
    'newCpuValue',
    18
    (event: any, data: any) => {
    19
    this.onNewCpuValue.next(data);
    20
    }
    21

    View Slide

  123. renderer proces
    @Injectable({ providedIn: 'root' })
    export class CpuValueService {
    private onNewCpuValue = new Subject();
    get newCpuValue(){
    return this.onNewCpuValue.asObservable();
    }
    constructor(private electronService: ElectronService) {
    if (environment.desktop) {
    this.registerCpuEvent();
    }
    }
    private registerCpuEvent() {
    if (this.electronService.ipcRenderer) {
    this.electronService.ipcRenderer.on(
    'newCpuValue',
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    constructor(private electronService: ElectronService) {
    if (environment.desktop) {
    this.registerCpuEvent();
    }
    }
    @Injectable({ providedIn: 'root' })
    1
    export class CpuValueService {
    2
    private onNewCpuValue = new Subject();
    3
    4
    get newCpuValue(){
    5
    return this.onNewCpuValue.asObservable();
    6
    }
    7
    8
    9
    10
    11
    12
    13
    14
    private registerCpuEvent() {
    15
    if (this.electronService.ipcRenderer) {
    16
    this.electronService.ipcRenderer.on(
    17
    'newCpuValue',
    18
    private registerCpuEvent() {
    if (this.electronService.ipcRenderer) {
    this.electronService.ipcRenderer.on(
    'newCpuValue',
    (event: any, data: any) => {
    this.onNewCpuValue.next(data);
    }
    );
    }
    }
    }
    7
    8
    constructor(private electronService: ElectronService) {
    9
    if (environment.desktop) {
    10
    this.registerCpuEvent();
    11
    }
    12
    }
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    }
    25

    View Slide

  124. renderer proces
    @Injectable({ providedIn: 'root' })
    export class CpuValueService {
    private onNewCpuValue = new Subject();
    get newCpuValue(){
    return this.onNewCpuValue.asObservable();
    }
    constructor(private electronService: ElectronService) {
    if (environment.desktop) {
    this.registerCpuEvent();
    }
    }
    private registerCpuEvent() {
    if (this.electronService.ipcRenderer) {
    this.electronService.ipcRenderer.on(
    'newCpuValue',
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    constructor(private electronService: ElectronService) {
    if (environment.desktop) {
    this.registerCpuEvent();
    }
    }
    @Injectable({ providedIn: 'root' })
    1
    export class CpuValueService {
    2
    private onNewCpuValue = new Subject();
    3
    4
    get newCpuValue(){
    5
    return this.onNewCpuValue.asObservable();
    6
    }
    7
    8
    9
    10
    11
    12
    13
    14
    private registerCpuEvent() {
    15
    if (this.electronService.ipcRenderer) {
    16
    this.electronService.ipcRenderer.on(
    17
    'newCpuValue',
    18
    private registerCpuEvent() {
    if (this.electronService.ipcRenderer) {
    this.electronService.ipcRenderer.on(
    'newCpuValue',
    @Injectable({ providedIn: 'root' })
    1
    export class CpuValueService {
    2
    private onNewCpuValue = new Subject();
    3
    4
    get newCpuValue(){
    5
    return this.onNewCpuValue.asObservable();
    6
    }
    7
    8
    constructor(private electronService: ElectronService) {
    9
    if (environment.desktop) {
    10
    this.registerCpuEvent();
    11
    }
    12
    }
    13
    14
    15
    16
    17
    18
    private onNewCpuValue = new Subject();
    get newCpuValue(){
    return this.onNewCpuValue.asObservable();
    }
    @Injectable({ providedIn: 'root' })
    1
    export class CpuValueService {
    2
    3
    4
    5
    6
    7
    8
    constructor(private electronService: ElectronService) {
    9
    if (environment.desktop) {
    10
    this.registerCpuEvent();
    11
    }
    12
    }
    13
    14
    private registerCpuEvent() {
    15
    if (this.electronService.ipcRenderer) {
    16
    this.electronService.ipcRenderer.on(
    17
    'newCpuValue',
    18

    View Slide

  125. $ npm install electron-packager -g

    View Slide

  126. $ electron-packager .temp/desktop

    View Slide

  127. $ electron-packager .temp/desktop --platform=linux, win32

    View Slide

  128. Automatic Updates
    Crash Reports
    Content Tracing
    Installation Packages

    View Slide

  129. View Slide

  130. Dem

    View Slide

  131. What about variation points?
    "
    "

    View Slide

  132. View Slide

  133. Dependenc Injectio

    View Slide

  134. @Injectable({
    providedIn: 'root',
    })
    export abstract class AbstractCameraService {
    abstract getPhoto(...): Observable;
    }
    1
    2
    3
    4
    5
    6

    View Slide

  135. @Injectable({
    providedIn: 'root',
    useFactory: cameraFactory,
    deps: [PlatformInformationService],
    })
    export abstract class AbstractCameraService {
    abstract getPhoto(...): Observable;
    }
    1
    2
    3
    4
    5
    6
    7
    8

    View Slide

  136. export function cameraFactory(
    platformInformationService: PlatformInformationService
    ): AbstractCameraService {
    return platformInformationService.isMobile
    ? new MobileCameraService()
    : new DesktopCameraService();
    }
    @Injectable({
    providedIn: 'root',
    useFactory: cameraFactory,
    deps: [PlatformInformationService],
    })
    export abstract class AbstractCameraService {
    abstract getPhoto(...): Observable;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    View Slide

  137. import {
    AbstractCameraService, Photo
    } from '@workspace/features/camera';
    @Component({ ... })
    export class ProfileDetailsComponent {
    constructor(
    private cameraService: AbstractCameraService
    ) {}
    pictureClicked() {
    this.cameraService.getPhoto()
    .subscribe((result: Photo) => {
    // ...
    });
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    View Slide

  138. import {
    AbstractCameraService, Photo
    } from '@workspace/features/camera';
    @Component({ ... })
    export class ProfileDetailsComponent {
    constructor(
    private cameraService: AbstractCameraService
    ) {}
    pictureClicked() {
    this.cameraService.getPhoto()
    .subscribe((result: Photo) => {
    // ...
    });
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import {
    AbstractCameraService, Photo
    } from '@workspace/features/camera';
    1
    2
    3
    4
    @Component({ ... })
    5
    export class ProfileDetailsComponent {
    6
    7
    constructor(
    8
    private cameraService: AbstractCameraService
    9
    ) {}
    10
    11
    pictureClicked() {
    12
    this.cameraService.getPhoto()
    13
    .subscribe((result: Photo) => {
    14
    // ...
    15
    });
    16
    }
    17
    }
    18

    View Slide

  139. import {
    AbstractCameraService, Photo
    } from '@workspace/features/camera';
    @Component({ ... })
    export class ProfileDetailsComponent {
    constructor(
    private cameraService: AbstractCameraService
    ) {}
    pictureClicked() {
    this.cameraService.getPhoto()
    .subscribe((result: Photo) => {
    // ...
    });
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import {
    AbstractCameraService, Photo
    } from '@workspace/features/camera';
    1
    2
    3
    4
    @Component({ ... })
    5
    export class ProfileDetailsComponent {
    6
    7
    constructor(
    8
    private cameraService: AbstractCameraService
    9
    ) {}
    10
    11
    pictureClicked() {
    12
    this.cameraService.getPhoto()
    13
    .subscribe((result: Photo) => {
    14
    // ...
    15
    });
    16
    }
    17
    }
    18
    constructor(
    private cameraService: AbstractCameraService
    ) {}
    import {
    1
    AbstractCameraService, Photo
    2
    } from '@workspace/features/camera';
    3
    4
    @Component({ ... })
    5
    export class ProfileDetailsComponent {
    6
    7
    8
    9
    10
    11
    pictureClicked() {
    12
    this.cameraService.getPhoto()
    13
    .subscribe((result: Photo) => {
    14
    // ...
    15
    });
    16
    }
    17
    }
    18

    View Slide

  140. import {
    AbstractCameraService, Photo
    } from '@workspace/features/camera';
    @Component({ ... })
    export class ProfileDetailsComponent {
    constructor(
    private cameraService: AbstractCameraService
    ) {}
    pictureClicked() {
    this.cameraService.getPhoto()
    .subscribe((result: Photo) => {
    // ...
    });
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import {
    AbstractCameraService, Photo
    } from '@workspace/features/camera';
    1
    2
    3
    4
    @Component({ ... })
    5
    export class ProfileDetailsComponent {
    6
    7
    constructor(
    8
    private cameraService: AbstractCameraService
    9
    ) {}
    10
    11
    pictureClicked() {
    12
    this.cameraService.getPhoto()
    13
    .subscribe((result: Photo) => {
    14
    // ...
    15
    });
    16
    }
    17
    }
    18
    constructor(
    private cameraService: AbstractCameraService
    ) {}
    import {
    1
    AbstractCameraService, Photo
    2
    } from '@workspace/features/camera';
    3
    4
    @Component({ ... })
    5
    export class ProfileDetailsComponent {
    6
    7
    8
    9
    10
    11
    pictureClicked() {
    12
    this.cameraService.getPhoto()
    13
    .subscribe((result: Photo) => {
    14
    // ...
    15
    });
    16
    }
    17
    }
    18
    pictureClicked() {
    this.cameraService.getPhoto()
    .subscribe((result: Photo) => {
    // ...
    });
    }
    import {
    1
    AbstractCameraService, Photo
    2
    } from '@workspace/features/camera';
    3
    4
    @Component({ ... })
    5
    export class ProfileDetailsComponent {
    6
    7
    constructor(
    8
    private cameraService: AbstractCameraService
    9
    ) {}
    10
    11
    12
    13
    14
    15
    16
    17
    }
    18

    View Slide

  141. View Slide

  142. Securit

    View Slide

  143. Mobil
    Desktop
    Web

    View Slide

  144. OAut 2
    OIDC

    View Slide

  145. https://bit.ly/3mMHyKY

    View Slide

  146. Alternative

    View Slide

  147. View Slide

  148. Progressiv
    Web
    App

    View Slide

  149. Realtim Cr
    Platfor App
    Angular, ASP.NET
    Cor & Signa R
    wit

    View Slide

  150. an yo !

    View Slide

  151. Fabian
    Gosebrink

    View Slide