Add react-native-desktop-menu native module
Signed-off-by: Vitaliy Vlasov <siphiuel@gmail.com>
This commit is contained in:
parent
c91e51459f
commit
dc4841f041
|
@ -72,6 +72,7 @@
|
||||||
"react-native/Libraries/vendor/emitter/EventEmitter"
|
"react-native/Libraries/vendor/emitter/EventEmitter"
|
||||||
"react-native-fetch-polyfill"
|
"react-native-fetch-polyfill"
|
||||||
"react-native-desktop-linking"
|
"react-native-desktop-linking"
|
||||||
|
"react-native-desktop-menu"
|
||||||
"react-native-desktop-notification"
|
"react-native-desktop-notification"
|
||||||
"text-encoding"
|
"text-encoding"
|
||||||
"js-sha3"
|
"js-sha3"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
#include <QGuiApplication>
|
#include <QApplication>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QQuickView>
|
#include <QQuickView>
|
||||||
|
@ -242,7 +242,7 @@ void renameRealmDirs() {
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QGuiApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
QCoreApplication::setApplicationName("Status");
|
QCoreApplication::setApplicationName("Status");
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
"node_modules/react-native-securerandom/desktop",
|
"node_modules/react-native-securerandom/desktop",
|
||||||
"modules/react-native-status/desktop",
|
"modules/react-native-status/desktop",
|
||||||
"modules/react-native-desktop-linking/desktop",
|
"modules/react-native-desktop-linking/desktop",
|
||||||
|
"modules/react-native-desktop-menu/desktop",
|
||||||
"modules/react-native-desktop-notification/desktop",
|
"modules/react-native-desktop-notification/desktop",
|
||||||
"node_modules/google-breakpad"
|
"node_modules/google-breakpad"
|
||||||
],
|
],
|
||||||
|
|
|
@ -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)
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
|
@ -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": ""
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
(def fetch (.-default (js/require "react-native-fetch-polyfill")))
|
(def fetch (.-default (js/require "react-native-fetch-polyfill")))
|
||||||
(def i18n (js/require "react-native-i18n"))
|
(def i18n (js/require "react-native-i18n"))
|
||||||
(def desktop-linking (.-DesktopLinking (.-NativeModules react-native)))
|
(def desktop-linking (.-DesktopLinking (.-NativeModules react-native)))
|
||||||
|
(def desktop-menu (js/require "react-native-desktop-menu"))
|
||||||
|
|
||||||
(def react-native-firebase #js {})
|
(def react-native-firebase #js {})
|
||||||
(def nfc-manager #js {})
|
(def nfc-manager #js {})
|
||||||
|
|
|
@ -27,3 +27,4 @@
|
||||||
(def background-timer (.-default (js/require "react-native-background-timer")))
|
(def background-timer (.-default (js/require "react-native-background-timer")))
|
||||||
(def react-navigation (js/require "react-navigation"))
|
(def react-navigation (js/require "react-navigation"))
|
||||||
(def desktop-linking #js {:addEventListener (fn [])})
|
(def desktop-linking #js {:addEventListener (fn [])})
|
||||||
|
(def desktop-menu #js {:addEventListener (fn [])})
|
||||||
|
|
|
@ -26,6 +26,7 @@ external_modules_dir=( \
|
||||||
'modules/react-native-status/desktop' \
|
'modules/react-native-status/desktop' \
|
||||||
'node_modules/google-breakpad' \
|
'node_modules/google-breakpad' \
|
||||||
'modules/react-native-desktop-linking/desktop' \
|
'modules/react-native-desktop-linking/desktop' \
|
||||||
|
'modules/react-native-desktop-menu/desktop' \
|
||||||
'modules/react-native-desktop-notification/desktop' \
|
'modules/react-native-desktop-notification/desktop' \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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?)))
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||||
[status-im.ui.screens.desktop.main.chat.styles :as styles]
|
[status-im.ui.screens.desktop.main.chat.styles :as styles]
|
||||||
[status-im.contact.db :as contact.db]
|
[status-im.contact.db :as contact.db]
|
||||||
|
[status-im.ui.components.popup-menu.views :as popup-menu]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.screens.desktop.main.chat.events :as chat.events]
|
[status-im.ui.screens.desktop.main.chat.events :as chat.events]
|
||||||
[status-im.ui.screens.chat.message.message :as chat.message]))
|
[status-im.ui.screens.chat.message.message :as chat.message]))
|
||||||
|
@ -49,24 +50,13 @@
|
||||||
public?
|
public?
|
||||||
[react/text {:style styles/public-chat-text}
|
[react/text {:style styles/public-chat-text}
|
||||||
(i18n/label :t/public-chat)])]]
|
(i18n/label :t/public-chat)])]]
|
||||||
[react/view
|
[react/touchable-highlight
|
||||||
(when (and (not group-chat) (not public?))
|
{:on-press #(popup-menu/show-desktop-menu
|
||||||
[react/text {:style (styles/profile-actions-text colors/black)
|
(popup-menu/get-chat-menu-items group-chat public? chat-id))}
|
||||||
:on-press #(re-frame/dispatch [:show-profile-desktop public-key])}
|
[vector-icons/icon :icons/dots-horizontal
|
||||||
(i18n/label :t/view-profile)])
|
{:style {:tint-color colors/black
|
||||||
(when (and group-chat (not public?))
|
:width 24
|
||||||
[react/text {:style (styles/profile-actions-text colors/black)
|
:height 24}}]]]))
|
||||||
: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)]]]))
|
|
||||||
|
|
||||||
(views/defview message-author-name [{:keys [from]}]
|
(views/defview message-author-name [{:keys [from]}]
|
||||||
(views/letsubs [incoming-name [:contacts/contact-name-by-identity from]]
|
(views/letsubs [incoming-name [:contacts/contact-name-by-identity from]]
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.screens.desktop.main.tabs.home.styles :as styles]
|
[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]
|
[clojure.string :as string]
|
||||||
[status-im.ui.screens.home.views.inner-item :as chat-item]
|
[status-im.ui.screens.home.views.inner-item :as chat-item]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
|
@ -57,8 +58,15 @@
|
||||||
[react/view {:style styles/timestamp}
|
[react/view {:style styles/timestamp}
|
||||||
[chat-item/message-timestamp (:timestamp last-message)]]])))
|
[chat-item/message-timestamp (:timestamp last-message)]]])))
|
||||||
|
|
||||||
(defn chat-list-item [[chat-id chat]]
|
(defn chat-list-item [[chat-id
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/navigate-to-chat 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)]])
|
[chat-list-item-inner-view (assoc chat :chat-id chat-id)]])
|
||||||
|
|
||||||
(defn tag-view [tag {:keys [on-press]}]
|
(defn tag-view [tag {:keys [on-press]}]
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
(def linear-gradient #js {})
|
(def linear-gradient #js {})
|
||||||
(def nfc #js {})
|
(def nfc #js {})
|
||||||
(def orientation #js {})
|
(def orientation #js {})
|
||||||
(def popup-menu #js {})
|
|
||||||
(def qr-code #js {})
|
(def qr-code #js {})
|
||||||
(def nfc-manager #js {:default #js {}})
|
(def nfc-manager #js {:default #js {}})
|
||||||
(def react-native
|
(def react-native
|
||||||
|
|
Loading…
Reference in New Issue