Skip to content

Commit

Permalink
Add react-native-desktop-menu native module
Browse files Browse the repository at this point in the history
Signed-off-by: Vitaliy Vlasov <siphiuel@gmail.com>
  • Loading branch information
Vitaliy Vlasov committed Dec 1, 2018
1 parent c91e514 commit dc4841f
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 23 deletions.
1 change: 1 addition & 0 deletions clj-rn.conf.edn
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"react-native/Libraries/vendor/emitter/EventEmitter"
"react-native-fetch-polyfill"
"react-native-desktop-linking"
"react-native-desktop-menu"
"react-native-desktop-notification"
"text-encoding"
"js-sha3"
Expand Down
4 changes: 2 additions & 2 deletions desktop/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <QDirIterator>
#include <QFile>
#include <QFontDatabase>
#include <QGuiApplication>
#include <QApplication>
#include <QMutexLocker>
#include <QProcess>
#include <QQuickView>
Expand Down Expand Up @@ -242,7 +242,7 @@ void renameRealmDirs() {

int main(int argc, char **argv) {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QApplication app(argc, argv);

QCoreApplication::setApplicationName("Status");

Expand Down
1 change: 1 addition & 0 deletions desktop_files/package.json.orig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"node_modules/react-native-securerandom/desktop",
"modules/react-native-status/desktop",
"modules/react-native-desktop-linking/desktop",
"modules/react-native-desktop-menu/desktop",
"modules/react-native-desktop-notification/desktop",
"node_modules/google-breakpad"
],
Expand Down
9 changes: 9 additions & 0 deletions modules/react-native-desktop-menu/desktop/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(REACT_NATIVE_DESKTOP_EXTERNAL_MODULES_TYPE_NAMES ${REACT_NATIVE_DESKTOP_EXTERNAL_MODULES_TYPE_NAMES}
\"DesktopMenu\" PARENT_SCOPE)

set(REACT_NATIVE_DESKTOP_EXTERNAL_MODULES_SRC ${REACT_NATIVE_DESKTOP_EXTERNAL_MODULES_SRC}
${CMAKE_CURRENT_SOURCE_DIR}/desktopmenu.cpp PARENT_SCOPE)

include(${CMAKE_ROOT}/Modules/ExternalProject.cmake)
64 changes: 64 additions & 0 deletions modules/react-native-desktop-menu/desktop/desktopmenu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "desktopmenu.h"
#include "bridge.h"

#include <QCoreApplication>
#include <QDebug>
#include <QMenu>
#include <QCursor>

Q_LOGGING_CATEGORY(DESKTOPMENU, "DesktopMenu")

namespace {
struct RegisterQMLMetaType {
RegisterQMLMetaType() { qRegisterMetaType<DesktopMenu *>(); }
} registerMetaType;
} // namespace

class DesktopMenuPrivate {
public:
Bridge *bridge = nullptr;
void createMenu(const QStringList& items, double callback);
private:
void onTriggered(QAction* action);
};

void DesktopMenuPrivate::createMenu(const QStringList& items, double callback) {
QMenu* menu = new QMenu();
for (const QString& name : items) {
menu->addAction(name);
}
QObject::connect(menu, &QMenu::triggered, [=](QAction* action) {
bridge->invokePromiseCallback(callback, QVariantList{action->text()});
});
QObject::connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater);
menu->popup(QCursor::pos());
}

DesktopMenu::DesktopMenu(QObject *parent)
: QObject(parent), d_ptr(new DesktopMenuPrivate) {
}

DesktopMenu::~DesktopMenu() {
}

void DesktopMenu::setBridge(Bridge *bridge) {
Q_D(DesktopMenu);

d->bridge = bridge;
}

QString DesktopMenu::moduleName() { return "DesktopMenuManager"; }

QList<ModuleMethod *> DesktopMenu::methodsToExport() {
return QList<ModuleMethod *>{};
}

QVariantMap DesktopMenu::constantsToExport() { return QVariantMap(); }

void DesktopMenu::show(const QStringList& items, double callback) {
Q_D(DesktopMenu);
d_ptr->createMenu(items, callback);

}


34 changes: 34 additions & 0 deletions modules/react-native-desktop-menu/desktop/desktopmenu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef DESKTOPMENU_H
#define DESKTOPMENU_H

#include "moduleinterface.h"

#include <QLoggingCategory>
#include <QVariantMap>

Q_DECLARE_LOGGING_CATEGORY(MENU)

class DesktopMenuPrivate;
class DesktopMenu : public QObject, public ModuleInterface {
Q_OBJECT
Q_INTERFACES(ModuleInterface)

Q_DECLARE_PRIVATE(DesktopMenu)

public:
Q_INVOKABLE DesktopMenu(QObject* parent = 0);
virtual ~DesktopMenu();

void setBridge(Bridge* bridge) override;

QString moduleName() override;
QList<ModuleMethod*> methodsToExport() override;
QVariantMap constantsToExport() override;

Q_INVOKABLE void show(const QStringList& items, double callback);

private:
QScopedPointer<DesktopMenuPrivate> d_ptr;
};

#endif // DESKTOPMENU_H
29 changes: 29 additions & 0 deletions modules/react-native-desktop-menu/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

type MenuItems = Array<{
text?: string,
onPress?: ?Function,
}>;

const NativeModules = require('react-native').NativeModules;

class DesktopMenu {

static show(
menuItems?: MenuItems
): void {
var itemNames = menuItems.map(i => i.text);
var itemMap = new Map();
for (let i = 0; i < menuItems.length; ++i) {
itemMap.set(menuItems[i].text, menuItems[i].onPress);
}
NativeModules.DesktopMenuManager.show(
itemNames,
(name) => {
(itemMap.get(name))();
}
);
}
}

module.exports = DesktopMenu;
13 changes: 13 additions & 0 deletions modules/react-native-desktop-menu/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"private": true,
"nativePackage": true,
"name": "react-native-desktop-menu",
"version": "1.0.0",
"description": "Native popup and context menus for Desktop",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
(def fetch (.-default (js/require "react-native-fetch-polyfill")))
(def i18n (js/require "react-native-i18n"))
(def desktop-linking (.-DesktopLinking (.-NativeModules react-native)))
(def desktop-menu (js/require "react-native-desktop-menu"))

(def react-native-firebase #js {})
(def nfc-manager #js {})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
(def background-timer (.-default (js/require "react-native-background-timer")))
(def react-navigation (js/require "react-navigation"))
(def desktop-linking #js {:addEventListener (fn [])})
(def desktop-menu #js {:addEventListener (fn [])})
1 change: 1 addition & 0 deletions scripts/build-desktop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ external_modules_dir=( \
'modules/react-native-status/desktop' \
'node_modules/google-breakpad' \
'modules/react-native-desktop-linking/desktop' \
'modules/react-native-desktop-menu/desktop' \
'modules/react-native-desktop-notification/desktop' \
)

Expand Down
28 changes: 28 additions & 0 deletions src/status_im/ui/components/popup_menu/views.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
(ns status-im.ui.components.popup-menu.views
(:require [status-im.ui.components.react :as react]
[status-im.react-native.js-dependencies :as rn-dependencies]
[status-im.utils.platform :as platform]
[status-im.i18n :as i18n]
[re-frame.core :as re-frame]
[taoensso.timbre :as log]))

(defn show-desktop-menu [items]
(.show rn-dependencies/desktop-menu
(clj->js (mapv #(hash-map :text (:text %1) :onPress (:on-select %1)) items))))

(defn get-chat-menu-items [group-chat public? chat-id]
(->> [(when (and (not group-chat) (not public?))
{:text (i18n/label :t/view-profile)
:on-select #(re-frame/dispatch [:show-profile-desktop chat-id])})
(when (and group-chat (not public?))
{:text (i18n/label :t/group-info)
:on-select #(re-frame/dispatch [:show-group-chat-profile])})
{:text (i18n/label :t/clear-history)
:on-select #(re-frame/dispatch [:chat.ui/clear-history-pressed])}
{:text (i18n/label :t/delete-chat)
:on-select #(re-frame/dispatch [(if (and group-chat (not public?))
:group-chats.ui/remove-chat-pressed
:chat.ui/remove-chat-pressed)
chat-id])}]
(remove nil?)))

26 changes: 8 additions & 18 deletions src/status_im/ui/screens/desktop/main/chat/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.screens.desktop.main.chat.styles :as styles]
[status-im.contact.db :as contact.db]
[status-im.ui.components.popup-menu.views :as popup-menu]
[status-im.i18n :as i18n]
[status-im.ui.screens.desktop.main.chat.events :as chat.events]
[status-im.ui.screens.chat.message.message :as chat.message]))
Expand Down Expand Up @@ -49,24 +50,13 @@
public?
[react/text {:style styles/public-chat-text}
(i18n/label :t/public-chat)])]]
[react/view
(when (and (not group-chat) (not public?))
[react/text {:style (styles/profile-actions-text colors/black)
:on-press #(re-frame/dispatch [:show-profile-desktop public-key])}
(i18n/label :t/view-profile)])
(when (and group-chat (not public?))
[react/text {:style (styles/profile-actions-text colors/black)
:on-press #(re-frame/dispatch [:show-group-chat-profile])}
(i18n/label :t/group-info)])
[react/text {:style (styles/profile-actions-text colors/black)
:on-press #(re-frame/dispatch [:chat.ui/clear-history-pressed])}
(i18n/label :t/clear-history)]
[react/text {:style (styles/profile-actions-text colors/black)
:on-press #(re-frame/dispatch [(if (and group-chat (not public?))
:group-chats.ui/remove-chat-pressed
:chat.ui/remove-chat-pressed)
chat-id])}
(i18n/label :t/delete-chat)]]]))
[react/touchable-highlight
{:on-press #(popup-menu/show-desktop-menu
(popup-menu/get-chat-menu-items group-chat public? chat-id))}
[vector-icons/icon :icons/dots-horizontal
{:style {:tint-color colors/black
:width 24
:height 24}}]]]))

(views/defview message-author-name [{:keys [from]}]
(views/letsubs [incoming-name [:contacts/contact-name-by-identity from]]
Expand Down
12 changes: 10 additions & 2 deletions src/status_im/ui/screens/desktop/main/tabs/home/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.screens.desktop.main.tabs.home.styles :as styles]
[status-im.ui.components.popup-menu.views :as popup-menu]
[clojure.string :as string]
[status-im.ui.screens.home.views.inner-item :as chat-item]
[taoensso.timbre :as log]
Expand Down Expand Up @@ -57,8 +58,15 @@
[react/view {:style styles/timestamp}
[chat-item/message-timestamp (:timestamp last-message)]]])))

(defn chat-list-item [[chat-id chat]]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])}
(defn chat-list-item [[chat-id
{:keys [group-chat public?] :as chat}]]
[react/touchable-highlight
{:on-press (fn [arg]
(let [right-click? (= "right" (.-button (.-nativeEvent arg)))]
(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])
(when right-click?
(popup-menu/show-desktop-menu
(popup-menu/get-chat-menu-items group-chat public? chat-id)))))}
[chat-list-item-inner-view (assoc chat :chat-id chat-id)]])

(defn tag-view [tag {:keys [on-press]}]
Expand Down
1 change: 0 additions & 1 deletion test/cljs/status_im/react_native/js_dependencies.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
(def linear-gradient #js {})
(def nfc #js {})
(def orientation #js {})
(def popup-menu #js {})
(def qr-code #js {})
(def nfc-manager #js {:default #js {}})
(def react-native
Expand Down

0 comments on commit dc4841f

Please sign in to comment.