private void addShareMessageRenderer(Identity arg) {
   executorService.submit(
       () -> {
         ShareNotificationRenderer renderer =
             new ShareNotificationRenderer(
                 ((BoxVolumeFactory) customProperties.get("boxVolumeFactory"))
                     .getVolume(config.getAccount(), arg)
                     .getReadBackend(),
                 sharingService);
         rendererFactory.addRenderer(
             DropMessageRepository.PAYLOAD_TYPE_SHARE_NOTIFICATION, renderer);
       });
 }
  @Override
  public void start(Stage stage) throws Exception {
    primaryStage = stage;
    setUserAgentStylesheet(STYLESHEET_MODENA);

    config = initDiContainer();

    SceneAntialiasing aa = SceneAntialiasing.BALANCED;
    primaryStage
        .getIcons()
        .setAll(
            new javafx.scene.image.Image(getClass().getResourceAsStream("/logo-invert_small.png")));
    Scene scene;

    Platform.setImplicitExit(false);
    primaryStage.setTitle(TITLE);
    scene = new Scene(new LoginView().getView(), 370, 550, true, aa);
    primaryStage.setScene(scene);

    config.addObserver(
        (o, arg) -> {
          Platform.runLater(
              () -> {
                if (arg instanceof Account) {
                  try {
                    ClientConfiguration configuration =
                        (ClientConfiguration) customProperties.get("clientConfiguration");
                    Account acc = (Account) arg;
                    AccountingServer server =
                        new AccountingServer(
                            new URI(acc.getProvider()), acc.getUser(), acc.getAuth());
                    AccountingHTTP accountingHTTP =
                        new AccountingHTTP(server, new AccountingProfile());

                    BoxVolumeFactory factory =
                        new BlockBoxVolumeFactory(
                            configuration.getDeviceId().getBytes(),
                            accountingHTTP,
                            identityRepository);
                    boxVolumeFactory = new CachedBoxVolumeFactory(factory);
                    customProperties.put("boxVolumeFactory", boxVolumeFactory);
                    sharingService = new BlockSharingService(dropMessageRepository, dropConnector);
                    customProperties.put("sharingService", sharingService);

                    new Thread(getSyncDaemon(config)).start();
                    new Thread(getDropDaemon(config)).start();
                    view = new LayoutView();
                    Parent view = this.view.getView();
                    Scene layoutScene = new Scene(view, 800, 600, true, aa);
                    Platform.runLater(() -> primaryStage.setScene(layoutScene));

                    if (config.getSelectedIdentity() != null) {
                      addShareMessageRenderer(config.getSelectedIdentity());
                    }
                  } catch (Exception e) {
                    logger.error("failed to init background services: " + e.getMessage(), e);
                    // TODO to something with the fault
                  }
                } else if (arg instanceof Identity) {
                  addShareMessageRenderer((Identity) arg);
                }
              });
        });

    dropMessageRepository.addObserver(new ShareNotificationHandler(config));

    setTrayIcon(primaryStage);

    Runtime.getRuntime()
        .addShutdownHook(
            new Thread() {
              public void run() {
                Platform.exit();
              }
            });
    primaryStage.show();
  }
  private ClientConfiguration initDiContainer() throws Exception {
    if (!Files.exists(DATABASE_FILE) && !Files.exists(DATABASE_FILE.getParent())) {
      Files.createDirectories(DATABASE_FILE.getParent());
    }

    Persistence<String> persistence =
        new SQLitePersistence(DATABASE_FILE.toFile().getAbsolutePath());
    transferManager = new MonitoredTransferManager(new DefaultTransferManager());
    customProperties.put("loadManager", transferManager);
    customProperties.put("transferManager", transferManager);
    customProperties.put("persistence", persistence);
    customProperties.put("dropUrlGenerator", new DropUrlGenerator("https://qdrop.prae.me"));
    identityRepository = new PersistenceIdentityRepository(persistence);
    customProperties.put("identityRepository", identityRepository);
    PersistenceAccountRepository accountRepository = new PersistenceAccountRepository(persistence);
    customProperties.put("accountRepository", accountRepository);
    contactRepository = new PersistenceContactRepository(persistence);
    customProperties.put("contactRepository", contactRepository);
    dropMessageRepository = new PersistenceDropMessageRepository(persistence);
    customProperties.put("dropMessageRepository", dropMessageRepository);
    customProperties.put("dropConnector", dropConnector);
    customProperties.put("reportHandler", new HockeyApp());
    ClientConfiguration clientConfig =
        getClientConfiguration(persistence, identityRepository, accountRepository);
    if (!clientConfig.hasDeviceId()) {
      clientConfig.setDeviceId(generateDeviceId());
    }
    PersistenceContactRepository contactRepository = new PersistenceContactRepository(persistence);
    customProperties.put("contactRepository", contactRepository);
    customProperties.put("clientConfiguration", clientConfig);
    customProperties.put("primaryStage", primaryStage);

    rendererFactory.setFallbackRenderer(new PlaintextMessageRenderer());
    customProperties.put("messageRendererFactory", rendererFactory);

    Injector.setConfigurationSource(customProperties::get);
    Injector.setInstanceSupplier(new RecursiveInjectionInstanceSupplier(customProperties));
    return clientConfig;
  }