Use multiple app instances simultaneously

Signed-off-by: Vitaliy Vlasov <siphiuel@gmail.com>
This commit is contained in:
Vitaliy Vlasov 2018-10-27 21:24:47 +02:00
parent 7e031e8008
commit 92d00f4250
No known key found for this signature in database
GPG Key ID: A7D57C347F2B2964
19 changed files with 147 additions and 51 deletions

View File

@ -9,7 +9,7 @@ pipeline {
"-v /dev/fuse:/dev/fuse "+
"-v /var/tmp/lein:/var/tmp/lein:rw "+
"-v /var/tmp/npm:/var/tmp/npm:rw "+
"-v /opt/StatusImAppImage.zip:/opt/StatusImAppImage.zip:ro"
"-v /opt/StatusImAppImage_20181113.zip:/opt/StatusImAppImage.zip:ro"
)
}
}

View File

@ -9,7 +9,7 @@ pipeline {
"-v /dev/fuse:/dev/fuse "+
"-v /var/tmp/lein:/var/tmp/lein:rw "+
"-v /var/tmp/npm:/var/tmp/npm:rw "+
"-v /opt/StatusIm-Windows-base-image.zip:/opt/StatusIm-Windows-base-image.zip:ro"
"-v /opt/StatusIm-Windows-base-image_20181113.zip:/opt/StatusIm-Windows-base-image.zip:ro"
)
}
}

View File

@ -67,6 +67,8 @@ class ReactNativeProperties : public QObject {
QString pluginsPath READ pluginsPath WRITE setPluginsPath NOTIFY pluginsPathChanged)
Q_PROPERTY(
QString executor READ executor WRITE setExecutor NOTIFY executorChanged)
Q_PROPERTY(
QVariantMap initialProps READ initialProps WRITE setInitialProps NOTIFY initialPropsChanged)
public:
ReactNativeProperties(QObject *parent = nullptr) : QObject(parent) {
m_codeLocation = m_packagerTemplate.arg(m_packagerHost).arg(m_packagerPort);
@ -99,6 +101,14 @@ public:
m_executor = executor;
Q_EMIT executorChanged();
}
QVariantMap initialProps() const { return m_initialProps; }
void setInitialProps(const QVariantMap &initialProps) {
if (m_initialProps == initialProps)
return;
m_initialProps = initialProps;
Q_EMIT initialPropsChanged();
}
QString packagerHost() const { return m_packagerHost; }
void setPackagerHost(const QString &packagerHost) {
if (m_packagerHost == packagerHost)
@ -130,11 +140,13 @@ public:
setLiveReload(false);
}
}
Q_SIGNALS:
void liveReloadChanged();
void codeLocationChanged();
void pluginsPathChanged();
void executorChanged();
void initialPropsChanged();
private:
bool m_liveReload = false;
@ -150,6 +162,7 @@ private:
#else
QString m_executor = "LocalServerConnection";
#endif
QVariantMap m_initialProps;
};
void saveMessage(QtMsgType type, const QMessageLogContext &context,
@ -197,8 +210,14 @@ bool redirectLogIntoFile() {
}
QString getDataStoragePath() {
QString dataStoragePath =
QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
QString statusDataDir = qgetenv("STATUS_DATA_DIR");
QString dataStoragePath;
if (!statusDataDir.isEmpty()) {
dataStoragePath = statusDataDir;
}
else {
dataStoragePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
}
QDir dir(dataStoragePath);
if (!dir.exists()) {
dir.mkpath(".");
@ -206,6 +225,21 @@ QString getDataStoragePath() {
return dataStoragePath;
}
void renameRealmDirs() {
QDir dataDir(getDataStoragePath());
qCDebug(STATUS) << "### path: " << getDataStoragePath();
if (dataDir.exists("default.realmaccounts")) {
dataDir.mkdir("default.realm");
dataDir.rename("default.realmaccounts", "default.realm/accounts");
dataDir.rename("default.realmdefault.realm", "default.realm/default.realm");
dataDir.rename("default.realmdefault.realm.lock", "default.realm/default.realm.lock");
dataDir.rename("default.realmdefault.realm.management", "default.realm/default.realm.management");
dataDir.rename("default.realmdefault.realm.note", "default.realm/default.realm.note");
}
}
int main(int argc, char **argv) {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
@ -215,12 +249,15 @@ int main(int argc, char **argv) {
QString appPath = QCoreApplication::applicationDirPath();
QString dataStoragePath = getDataStoragePath();
#ifdef BUILD_FOR_BUNDLE
killZombieJsServer();
if (qgetenv("STATUS_DATA_DIR").isEmpty()) {
killZombieJsServer();
}
#else
appPath.append(CRASH_REPORT_EXECUTABLE_RELATIVE_PATH);
dataStoragePath = "";
#endif
renameRealmDirs();
ExceptionGlobalHandler exceptionHandler(
appPath + QDir::separator() + CRASH_REPORT_EXECUTABLE,
exceptionPostHandledCallback, dataStoragePath);
@ -251,6 +288,19 @@ int main(int argc, char **argv) {
QQuickView view;
ReactNativeProperties *rnp = new ReactNativeProperties(&view);
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QVariantMap initialProps;
QString statusNodePort = env.value("STATUS_NODE_PORT");
QString statusDataDir = env.value("STATUS_DATA_DIR");
if (!statusNodePort.isEmpty()) {
initialProps["STATUS_NODE_PORT"] = statusNodePort;
}
if (!statusDataDir.isEmpty()) {
initialProps["STATUS_DATA_DIR"] = statusDataDir;
}
rnp->setInitialProps(initialProps);
#ifdef BUILD_FOR_BUNDLE
rnp->setCodeLocation("file:" + QGuiApplication::applicationDirPath() +
"/assets");
@ -386,6 +436,11 @@ bool runNodeJsServer() {
g_nodeJsServerProcess = new QProcess();
g_nodeJsServerProcess->setWorkingDirectory(getDataStoragePath());
g_nodeJsServerProcess->setProgram(QGuiApplication::applicationDirPath() + QDir::separator() + NODEJS_SERVER_NAME);
QString port = qgetenv("REACT_SERVER_PORT");
if (!port.isEmpty()) {
QStringList arguments = (QStringList() << "--port" << port);
g_nodeJsServerProcess->setArguments(arguments);
}
QObject::connect(g_nodeJsServerProcess, &QProcess::errorOccurred,
[=](QProcess::ProcessError) {
qCWarning(JSSERVER) << "process name: "

View File

@ -13,10 +13,10 @@
(assert (exists? core/app-root) "Fatal Error - Your core.cljs file doesn't define an 'app-root' function!!! - Perhaps there was a compilation failure?")
(def cnt (r/atom 0))
(defn reloader [] @cnt [core/app-root])
(defn reloader [props] @cnt [core/app-root props])
;; Do not delete, root-el is used by the figwheel-bridge.js
(def root-el (r/as-element [reloader]))
(def root-el (r/reactify-component reloader))
(figwheel/start {:websocket-url (:android conf/figwheel-urls)
:heads-up-display false

View File

@ -13,10 +13,10 @@
(assert (exists? core/app-root) "Fatal Error - Your core.cljs file doesn't define an 'app-root' function!!! - Perhaps there was a compilation failure?")
(def cnt (r/atom 0))
(defn reloader [] @cnt [core/app-root])
(defn reloader [props] @cnt [core/app-root props])
;; Do not delete, root-el is used by the figwheel-bridge.js
(def root-el (r/as-element [reloader]))
(def root-el (r/reactify-component reloader))
(figwheel/start {:websocket-url (:desktop conf/figwheel-urls)
:heads-up-display false

View File

@ -13,10 +13,10 @@
(assert (exists? core/app-root) "Fatal Error - Your core.cljs file doesn't define an 'app-root' function!!! - Perhaps there was a compilation failure?")
(def cnt (r/atom 0))
(defn reloader [] @cnt [core/app-root])
(defn reloader [props] @cnt [core/app-root props])
;; Do not delete, root-el is used by the figwheel-bridge.js
(def root-el (r/as-element [reloader]))
(def root-el (r/reactify-component reloader))
(figwheel/start {:websocket-url (:ios conf/figwheel-urls)
:heads-up-display false

View File

@ -78,7 +78,7 @@ var figwheelApp = function (platform, devHost) {
</ReactNative.View>
);
}
return this.state.root;
return React.createElement(this.state.root, this.props);
},
componentDidMount: function () {

View File

@ -92,7 +92,15 @@ void RCTStatus::startNode(QString configString) {
if (!relativeDataDirPath.startsWith("/"))
relativeDataDirPath.prepend("/");
QString rootDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
QString statusDataDir = qgetenv("STATUS_DATA_DIR");
QString rootDirPath;
if (!statusDataDir.isEmpty()) {
rootDirPath = statusDataDir;
}
else {
rootDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
}
QDir rootDir(rootDirPath);
QString absDataDirPath = rootDirPath + relativeDataDirPath;
QDir dataDir(absDataDirPath);

View File

@ -227,7 +227,7 @@ function bundleWindows() {
if [ -z $STATUSIM_WINDOWS_BASEIMAGE_ZIP ]; then
STATUSIM_WINDOWS_BASEIMAGE_ZIP=./StatusIm-Windows-base-image.zip
[ -f $STATUSIM_WINDOWS_BASEIMAGE_ZIP ] || wget https://desktop-app-files.ams3.digitaloceanspaces.com/StatusIm-Windows-base-image.zip
[ -f $STATUSIM_WINDOWS_BASEIMAGE_ZIP ] || wget https://desktop-app-files.ams3.digitaloceanspaces.com/StatusIm-Windows-base-image_20181113.zip -O StatusIm-Windows-base-image.zip
fi
unzip "$STATUSIM_WINDOWS_BASEIMAGE_ZIP" -d Windows/
@ -271,11 +271,11 @@ function bundleLinux() {
echo "Creating AppImage..."
pushd $WORKFOLDER
rm -rf StatusImAppImage
rm -rf StatusImAppImage*
# TODO this needs to be fixed: status-react/issues/5378
if [ -z $STATUSIM_APPIMAGE ]; then
STATUSIM_APPIMAGE=./StatusImAppImage.zip
[ -f $STATUSIM_APPIMAGE ] || wget https://desktop-app-files.ams3.digitaloceanspaces.com/StatusImAppImage.zip
[ -f $STATUSIM_APPIMAGE ] || wget https://desktop-app-files.ams3.digitaloceanspaces.com/StatusImAppImage_20181113.zip -O StatusImAppImage.zip
fi
unzip "$STATUSIM_APPIMAGE" -d .
rm -rf AppDir
@ -351,7 +351,7 @@ function bundleMacOS() {
pushd $WORKFOLDER
rm -rf Status.app
# TODO this needs to be fixed: status-react/issues/5378
[ -f ./Status.app.zip ] || curl -L -o Status.app.zip https://desktop-app-files.ams3.digitaloceanspaces.com/Status.app.zip
[ -f ./Status.app.zip ] || curl -L -o Status.app.zip https://desktop-app-files.ams3.digitaloceanspaces.com/Status_20181113.app.zip
echo -e "${GREEN}Downloading done.${NC}"
echo ""
unzip ./Status.app.zip

View File

@ -17,7 +17,7 @@
(defn app-state-change-handler [state]
(dispatch [:app-state-change state]))
(defn app-root []
(defn app-root [props]
(let [keyboard-height (subscribe [:get :keyboard-height])]
(reagent/create-class
{:component-will-mount
@ -39,7 +39,8 @@
(.hide react/splash-screen)
(.addEventListener react/app-state "change" app-state-change-handler))
:component-did-mount
(fn []
(fn [this]
(dispatch [:set-initial-props (reagent/props this)])
;; TODO(oskarth): Background click_action handler
(notifications/init))
:component-will-unmount

View File

@ -2,6 +2,7 @@
(:require [goog.object :as object]
[goog.string :as gstr]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.data-store.realm.schemas.account.core :as account]
[status-im.data-store.realm.schemas.base.core :as base]
[taoensso.timbre :as log]
@ -65,29 +66,40 @@
(def old-base-realm-path
(.-defaultPath rn-dependencies/realm))
(def realm-dir
(defn realm-dir []
"This has to be a fn because otherwise re-frame app-db is not
initialized yet"
(if-let [path (utils.platform/no-backup-directory)]
(str path "/realm/")
(.-defaultPath rn-dependencies/realm)))
(let [initial-props @(re-frame/subscribe [:initial-props])
status-data-dir (get initial-props :STATUS_DATA_DIR)]
(cond-> (if status-data-dir
(str status-data-dir "/default.realm")
(.-defaultPath rn-dependencies/realm))
utils.platform/desktop?
(str "/")))))
(def old-realm-dir
(string/replace old-base-realm-path #"default\.realm$" ""))
(def accounts-realm-dir
(str realm-dir "accounts/"))
(defn accounts-realm-dir []
(str (realm-dir) "accounts/"))
(def base-realm-path
(str realm-dir
"default.realm"))
(defn base-realm-path []
(str (realm-dir) "default.realm"))
(defn get-account-db-path
[address]
(str (accounts-realm-dir) (utils.ethereum/sha3 address)))
(defn delete-realms []
(log/warn "realm: deleting all realms")
(fs/unlink realm-dir))
(fs/unlink (realm-dir)))
(defn delete-account-realm
[address]
(log/warn "realm: deleting account db " (utils.ethereum/sha3 address))
(let [file (str accounts-realm-dir (utils.ethereum/sha3 address))]
(let [file (get-account-db-path address)]
(.. (fs/unlink file)
(then #(fs/unlink (str file ".lock")))
(then #(fs/unlink (str file ".management")))
@ -95,14 +107,14 @@
(defn ensure-directories []
(..
(fs/mkdir realm-dir)
(then #(fs/mkdir accounts-realm-dir))))
(fs/mkdir (realm-dir))
(then #(fs/mkdir (accounts-realm-dir)))))
(defn- move-realm-to-library [path]
(let [filename (last (string/split path "/"))
new-path (if (is-account-file? path)
(str accounts-realm-dir (utils.ethereum/sha3 filename))
(str realm-dir filename))]
(get-account-db-path filename)
(str (realm-dir) filename))]
(log/debug "realm: moving " path " to " new-path)
(if (realm-management-file? path)
(fs/unlink path)
@ -177,7 +189,7 @@
(log/debug "Opening base realm... (first run)")
(when @base-realm
(close @base-realm))
(reset! base-realm (migrate-realm base-realm-path base/schemas encryption-key))
(reset! base-realm (migrate-realm (base-realm-path) base/schemas encryption-key))
(log/debug "Created @base-realm"))
(defn re-encrypt-realm
@ -212,10 +224,6 @@
(on-error {:error :write-copy-to-failed
:message message})))))))
(defn get-account-db-path
[address]
(str accounts-realm-dir (utils.ethereum/sha3 address)))
(defn check-db-encryption
[address password old-key]
(let [file-name (get-account-db-path address)

View File

@ -1,18 +1,23 @@
(ns status-im.desktop.core
(:require [reagent.core :as reagent]
[re-frame.core :as re-frame]
status-im.utils.db
status-im.ui.screens.db
status-im.ui.screens.events
status-im.ui.screens.subs
status-im.data-store.core
[reagent.impl.component :as reagent.component]
[status-im.ui.screens.desktop.views :as views]
[status-im.core :as core]
[status-im.desktop.deep-links :as deep-links]))
(defn app-root []
(defn app-root [props]
(reagent/create-class
{:component-did-mount deep-links/add-event-listener
:reagent-render views/main}))
{:component-did-mount (fn [this]
(re-frame/dispatch [:set-initial-props (reagent/props this)])
(deep-links/add-event-listener))
:reagent-render (fn [props]
views/main)}))
(defn init []
(core/init app-root))

View File

@ -1169,6 +1169,11 @@
(fn [cofx _]
(pairing/send-installation-messages cofx)))
(handlers/register-handler-fx
:set-initial-props
(fn [cofx [_ initial-props]]
{:db (assoc (:db cofx) :initial-props initial-props)}))
(handlers/register-handler-fx
:pairing.ui/enable-installation-pressed
(fn [cofx [_ installation-id]]

View File

@ -78,11 +78,13 @@
(fx/defn initialize-app-db
"Initialize db to initial state"
[{{:keys [status-module-initialized? view-id hardwallet
initial-props
network-status network peers-count peers-summary device-UUID]
:node/keys [status]
:or {network (get app-db :network)}} :db}]
{:db (assoc app-db
:contacts/contacts {}
:initial-props initial-props
:network-status network-status
:peers-count (or peers-count 0)
:peers-summary (or peers-summary [])

View File

@ -15,7 +15,7 @@
(defn app-state-change-handler [state]
(dispatch [:app-state-change state]))
(defn app-root []
(defn app-root [props]
(let [keyboard-height (subscribe [:get :keyboard-height])]
(reagent/create-class
{:component-will-mount
@ -34,7 +34,8 @@
(.hide react/splash-screen)
(.addEventListener react/app-state "change" app-state-change-handler))
:component-did-mount
(fn []
(fn [this]
(dispatch [:set-initial-props (reagent/props this)])
(notifications/init))
:component-will-unmount
(fn []

View File

@ -54,12 +54,16 @@
(get-in db [:accounts/accounts address :network]))
(defn- get-base-node-config [config]
(cond-> (assoc config
:Name "StatusIM"
:BackupDisabledDataDir (utils.platform/no-backup-directory))
config/dev-build?
(assoc :ListenAddr ":30304"
:DataDir (str (:DataDir config) "_dev"))))
(let [initial-props @(re-frame/subscribe [:initial-props])
status-node-port (get initial-props :STATUS_NODE_PORT)]
(cond-> (assoc config
:Name "StatusIM"
:BackupDisabledDataDir (utils.platform/no-backup-directory))
config/dev-build?
(assoc :ListenAddr ":30304"
:DataDir (str (:DataDir config) "_dev"))
status-node-port
(assoc :ListenAddr (str ":" status-node-port)))))
(defn- pick-nodes
"Picks `limit` different nodes randomly from the list of nodes

View File

@ -57,6 +57,7 @@
:chat/last-outgoing-message-sent-at 0
:chat/spam-messages-frequency 0
:tooltips {}
:initial-props {}
:desktop/desktop {:tab-view-id :home}
:dimensions/window (dimensions/window)
:push-notifications/stored {}
@ -148,6 +149,7 @@
(spec/def :desktop/desktop (spec/nilable any?))
(spec/def ::tooltips (spec/nilable any?))
(spec/def ::initial-props (spec/nilable any?))
;;;;NETWORK
@ -254,6 +256,7 @@
::was-modal?
::rpc-url
::tooltips
::initial-props
::web3
::web3-node-version
::webview-bridge

View File

@ -91,3 +91,7 @@
(reg-sub :dimensions/window-width
:<- [:dimensions/window]
:width)
(reg-sub :initial-props
(fn [db _]
(get db :initial-props)))

View File

@ -119,9 +119,9 @@ if (process.argv.indexOf('--pipe') != -1) {
rnUbuntuServer(process.stdin, process.stdout);
} else {
var port = process.env['REACT_SERVER_PORT'] || 5000;
process.argv.forEach((val) => {
if (val.indexOf('--port') != -1) {
port = val.substring(7);
process.argv.forEach((val, index) => {
if (val == '--port') {
port = process.argv[++index];
}
});