mirror of https://github.com/Nheko-Reborn/nheko
parent
1dc20f9164
commit
8a1666bc88
After Width: | Height: | Size: 429 B |
@ -1,23 +0,0 @@ |
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors |
||||
// |
||||
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
|
||||
import "../" |
||||
import QtQuick 2.10 |
||||
import QtQuick.Controls 2.1 |
||||
import im.nheko 1.0 |
||||
import im.nheko.EmojiModel 1.0 |
||||
|
||||
ImageButton { |
||||
id: emojiButton |
||||
|
||||
property var colors: currentActivePalette |
||||
property var emojiPicker |
||||
property string event_id |
||||
|
||||
image: ":/icons/icons/ui/smile.png" |
||||
onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.show(emojiButton, function(emoji) { |
||||
room.input.reaction(event_id, emoji); |
||||
TimelineManager.focusMessageInput(); |
||||
}) |
||||
} |
@ -0,0 +1,174 @@ |
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors |
||||
// |
||||
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
|
||||
import "../" |
||||
import QtGraphicalEffects 1.0 |
||||
import QtQuick 2.9 |
||||
import QtQuick.Controls 2.3 |
||||
import QtQuick.Layouts 1.3 |
||||
import im.nheko 1.0 |
||||
import im.nheko.EmojiModel 1.0 |
||||
|
||||
Menu { |
||||
id: stickerPopup |
||||
|
||||
property var callback |
||||
property var colors |
||||
property alias model: gridView.model |
||||
property var textArea |
||||
property real highlightHue: Nheko.colors.highlight.hslHue |
||||
property real highlightSat: Nheko.colors.highlight.hslSaturation |
||||
property real highlightLight: Nheko.colors.highlight.hslLightness |
||||
readonly property int stickerDim: 128 |
||||
readonly property int stickerDimPad: 128 + Nheko.paddingSmall |
||||
readonly property int stickersPerRow: 3 |
||||
|
||||
function show(showAt, model_, callback) { |
||||
console.debug("Showing sticker picker"); |
||||
model = model_; |
||||
stickerPopup.callback = callback; |
||||
popup(showAt ? showAt : null); |
||||
} |
||||
|
||||
margins: 0 |
||||
bottomPadding: 1 |
||||
leftPadding: 1 |
||||
rightPadding: 1 |
||||
modal: true |
||||
focus: true |
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside |
||||
//height: columnView.implicitHeight + 4 |
||||
//width: columnView.implicitWidth |
||||
width: stickersPerRow * stickerDimPad + 20 |
||||
|
||||
Rectangle { |
||||
color: Nheko.colors.window |
||||
height: columnView.implicitHeight + 4 |
||||
width: stickersPerRow * stickerDimPad + 20 |
||||
|
||||
ColumnLayout { |
||||
id: columnView |
||||
|
||||
spacing: 0 |
||||
anchors.leftMargin: 3 |
||||
anchors.rightMargin: 3 |
||||
anchors.bottom: parent.bottom |
||||
anchors.left: parent.left |
||||
anchors.right: parent.right |
||||
anchors.topMargin: 2 |
||||
|
||||
// Search field |
||||
TextField { |
||||
id: emojiSearch |
||||
|
||||
Layout.topMargin: 3 |
||||
Layout.preferredWidth: stickersPerRow * stickerDimPad + 20 - 6 |
||||
palette: Nheko.colors |
||||
background: null |
||||
placeholderTextColor: Nheko.colors.buttonText |
||||
color: Nheko.colors.text |
||||
placeholderText: qsTr("Search") |
||||
selectByMouse: true |
||||
rightPadding: clearSearch.width |
||||
onTextChanged: searchTimer.restart() |
||||
onVisibleChanged: { |
||||
if (visible) |
||||
forceActiveFocus(); |
||||
|
||||
} |
||||
|
||||
Timer { |
||||
id: searchTimer |
||||
|
||||
interval: 350 // tweak as needed? |
||||
onTriggered: stickerPopup.model.searchString = emojiSearch.text |
||||
} |
||||
|
||||
ToolButton { |
||||
id: clearSearch |
||||
|
||||
visible: emojiSearch.text !== '' |
||||
icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) |
||||
focusPolicy: Qt.NoFocus |
||||
onClicked: emojiSearch.clear() |
||||
hoverEnabled: true |
||||
background: null |
||||
|
||||
anchors { |
||||
verticalCenter: parent.verticalCenter |
||||
right: parent.right |
||||
} |
||||
// clear the default hover effects. |
||||
|
||||
Image { |
||||
height: parent.height - 2 * Nheko.paddingSmall |
||||
width: height |
||||
source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) |
||||
|
||||
anchors { |
||||
verticalCenter: parent.verticalCenter |
||||
right: parent.right |
||||
margins: Nheko.paddingSmall |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
// emoji grid |
||||
GridView { |
||||
id: gridView |
||||
|
||||
Layout.preferredHeight: cellHeight * 3.5 |
||||
Layout.preferredWidth: stickersPerRow * stickerDimPad + 20 |
||||
Layout.leftMargin: 4 |
||||
cellWidth: stickerDimPad |
||||
cellHeight: stickerDimPad |
||||
boundsBehavior: Flickable.StopAtBounds |
||||
clip: true |
||||
currentIndex: -1 // prevent sorting from stealing focus |
||||
cacheBuffer: 500 |
||||
|
||||
// Individual emoji |
||||
delegate: AbstractButton { |
||||
width: stickerDim |
||||
height: stickerDim |
||||
hoverEnabled: true |
||||
ToolTip.text: ":" + model.shortcode + ": - " + model.body |
||||
ToolTip.visible: hovered |
||||
// TODO: maybe add favorites at some point? |
||||
onClicked: { |
||||
console.debug("Picked " + model.shortcode); |
||||
stickerPopup.close(); |
||||
callback(model.originalRow); |
||||
} |
||||
|
||||
contentItem: Image { |
||||
height: stickerDim |
||||
width: stickerDim |
||||
source: model.url.replace("mxc://", "image://MxcImage/") |
||||
fillMode: Image.PreserveAspectFit |
||||
} |
||||
|
||||
background: Rectangle { |
||||
anchors.fill: parent |
||||
color: hovered ? Nheko.colors.highlight : 'transparent' |
||||
radius: 5 |
||||
} |
||||
|
||||
} |
||||
|
||||
ScrollBar.vertical: ScrollBar { |
||||
id: emojiScroll |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,91 @@ |
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "ImagePackModel.h" |
||||
|
||||
#include "Cache_p.h" |
||||
#include "CompletionModelRoles.h" |
||||
|
||||
ImagePackModel::ImagePackModel(const std::string &roomId, bool stickers, QObject *parent) |
||||
: QAbstractListModel(parent) |
||||
, room_id(roomId) |
||||
{ |
||||
auto accountpackV = |
||||
cache::client()->getAccountData(mtx::events::EventType::ImagePackInAccountData); |
||||
auto enabledRoomPacksV = |
||||
cache::client()->getAccountData(mtx::events::EventType::ImagePackRooms); |
||||
|
||||
std::optional<mtx::events::msc2545::ImagePack> accountPack; |
||||
if (accountpackV) { |
||||
auto tmp = |
||||
std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePack>>( |
||||
&*accountpackV); |
||||
if (tmp) |
||||
accountPack = tmp->content; |
||||
} |
||||
// mtx::events::msc2545::ImagePackRooms *enabledRoomPacks = nullptr;
|
||||
// if (enabledRoomPacksV)
|
||||
// enabledRoomPacks =
|
||||
// std::get_if<mtx::events::msc2545::ImagePackRooms>(&*enabledRoomPacksV);
|
||||
|
||||
if (accountPack && (!accountPack->pack || (stickers ? accountPack->pack->is_sticker() |
||||
: accountPack->pack->is_emoji()))) { |
||||
QString packname; |
||||
if (accountPack->pack) |
||||
packname = QString::fromStdString(accountPack->pack->display_name); |
||||
|
||||
for (const auto &img : accountPack->images) { |
||||
if (img.second.overrides_usage() && |
||||
(stickers ? !img.second.is_sticker() : !img.second.is_emoji())) |
||||
continue; |
||||
|
||||
ImageDesc i{}; |
||||
i.shortcode = QString::fromStdString(img.first); |
||||
i.packname = packname; |
||||
i.image = img.second; |
||||
images.push_back(std::move(i)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
QHash<int, QByteArray> |
||||
ImagePackModel::roleNames() const |
||||
{ |
||||
return { |
||||
{CompletionModel::CompletionRole, "completionRole"}, |
||||
{CompletionModel::SearchRole, "searchRole"}, |
||||
{CompletionModel::SearchRole2, "searchRole2"}, |
||||
{Roles::Url, "url"}, |
||||
{Roles::ShortCode, "shortcode"}, |
||||
{Roles::Body, "body"}, |
||||
{Roles::PackName, "packname"}, |
||||
{Roles::OriginalRow, "originalRow"}, |
||||
}; |
||||
} |
||||
|
||||
QVariant |
||||
ImagePackModel::data(const QModelIndex &index, int role) const |
||||
{ |
||||
if (hasIndex(index.row(), index.column(), index.parent())) { |
||||
switch (role) { |
||||
case CompletionModel::CompletionRole: |
||||
return QString::fromStdString(images[index.row()].image.url); |
||||
case Roles::Url: |
||||
return QString::fromStdString(images[index.row()].image.url); |
||||
case CompletionModel::SearchRole: |
||||
case Roles::ShortCode: |
||||
return images[index.row()].shortcode; |
||||
case CompletionModel::SearchRole2: |
||||
case Roles::Body: |
||||
return QString::fromStdString(images[index.row()].image.body); |
||||
case Roles::PackName: |
||||
return images[index.row()].packname; |
||||
case Roles::OriginalRow: |
||||
return index.row(); |
||||
default: |
||||
return {}; |
||||
} |
||||
} |
||||
return {}; |
||||
} |
@ -0,0 +1,52 @@ |
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once |
||||
|
||||
#include <QAbstractListModel> |
||||
|
||||
#include <mtx/events/mscs/image_packs.hpp> |
||||
|
||||
class ImagePackModel : public QAbstractListModel |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
enum Roles |
||||
{ |
||||
Url = Qt::UserRole, |
||||
ShortCode, |
||||
Body, |
||||
PackName, |
||||
OriginalRow, |
||||
}; |
||||
|
||||
ImagePackModel(const std::string &roomId, bool stickers, QObject *parent = nullptr); |
||||
QHash<int, QByteArray> roleNames() const override; |
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override |
||||
{ |
||||
(void)parent; |
||||
return (int)images.size(); |
||||
} |
||||
QVariant data(const QModelIndex &index, int role) const override; |
||||
|
||||
mtx::events::msc2545::PackImage imageAt(int row) |
||||
{ |
||||
if (row < 0 || static_cast<size_t>(row) >= images.size()) |
||||
return {}; |
||||
return images.at(static_cast<size_t>(row)).image; |
||||
} |
||||
|
||||
private: |
||||
std::string room_id; |
||||
|
||||
struct ImageDesc |
||||
{ |
||||
QString shortcode; |
||||
QString packname; |
||||
|
||||
mtx::events::msc2545::PackImage image; |
||||
}; |
||||
|
||||
std::vector<ImageDesc> images; |
||||
}; |
Loading…
Reference in new issue