Compare commits

..

1 Commits

Author SHA1 Message Date
ivan tkachenko
6466f7f56c Ban anything that flickers or flashes on hover
I don't like that. UI shouldn't jump in user's face like all these hover
actions, bright backgrounds and random layout-shifting buttons out of
nowhere.
2023-09-10 21:59:45 +03:00
100 changed files with 8189 additions and 8491 deletions

View File

@@ -82,7 +82,7 @@ set_package_properties(Qt${QT_MAJOR_VERSION} PROPERTIES
TYPE REQUIRED
PURPOSE "Basic application components"
)
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} COMPONENTS Kirigami2 I18n Notifications Config CoreAddons Sonnet ItemModels SyntaxHighlighting)
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} COMPONENTS Kirigami2 I18n Notifications Config CoreAddons Sonnet ItemModels)
set_package_properties(KF${QT_MAJOR_VERSION} PROPERTIES
TYPE REQUIRED
PURPOSE "Basic application components"

View File

@@ -159,7 +159,6 @@ to provide a convergent experience across multiple platforms.</p>
<li xml:lang="ko">투표 - MSC3381</li>
<li xml:lang="nl">Polls - MSC3381</li>
<li xml:lang="nn">Avstemmingar  MSC3381</li>
<li xml:lang="pl">Ankiety - MSC3381</li>
<li xml:lang="pt">Inquéritos - MSC3381</li>
<li xml:lang="sl">Polls - MSC3381</li>
<li xml:lang="sv">Polls - MSC3381</li>
@@ -184,7 +183,6 @@ to provide a convergent experience across multiple platforms.</p>
<li xml:lang="ko">스티커 팩 - MSC2545</li>
<li xml:lang="nl">Sticker Packs - MSC2545</li>
<li xml:lang="nn">Klistremerke-pakkar  MSC2545</li>
<li xml:lang="pl">Paczki naklejek - MSC2545</li>
<li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li>
<li xml:lang="sl">Sticker Packs - MSC2545</li>
<li xml:lang="sv">Sticker Packs - MSC2545</li>
@@ -209,7 +207,6 @@ to provide a convergent experience across multiple platforms.</p>
<li xml:lang="ko">위치 이벤트 - MSC3488</li>
<li xml:lang="nl">Locatie gebeurtenissen - MSC3488</li>
<li xml:lang="nn">Posisjonshendingar  MSC3488</li>
<li xml:lang="pl">Wydarzenia w miejscach - MSC3488</li>
<li xml:lang="pt">Eventos com Localizações - MSC3488</li>
<li xml:lang="sl">Location Events - MSC3488</li>
<li xml:lang="sv">Location Events - MSC3488</li>
@@ -297,7 +294,6 @@ to provide a convergent experience across multiple platforms.</p>
<caption xml:lang="ko">대화방 목록, 채팅, 대화방 정보가 표시된 주 보기</caption>
<caption xml:lang="nl">Hoofdweergave met lijst met rooms, chat en roominformatie</caption>
<caption xml:lang="nn">Hovudvising med romliste, pratevindauge og rominformasjon</caption>
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
<caption xml:lang="sv">Huvudvy med rumslista, chatt, och rumsinformation</caption>
@@ -323,7 +319,6 @@ to provide a convergent experience across multiple platforms.</p>
<caption xml:lang="ko">로그인 화면</caption>
<caption xml:lang="nl">Aanmeldscherm</caption>
<caption xml:lang="nn">Innloggingsbilete</caption>
<caption xml:lang="pl">Ekran logowania</caption>
<caption xml:lang="pt">Ecrã de autenticação</caption>
<caption xml:lang="sl">Prijavni zaslon</caption>
<caption xml:lang="sv">Inloggningsfönster</caption>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -136,7 +136,6 @@ add_library(neochat STATIC
mediasizehelper.h
eventhandler.cpp
enums/delegatetype.h
messageformatter.cpp
)
ecm_qt_declare_logging_category(neochat
@@ -200,7 +199,7 @@ else()
endif()
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 Qt::Xml KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels KF${QT_MAJOR_VERSION}::SyntaxHighlighting Quotient${QUOTIENT_SUFFIX} cmark::cmark QCoro::Core)
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient${QUOTIENT_SUFFIX} cmark::cmark QCoro::Core)
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)

View File

@@ -371,6 +371,36 @@ void Controller::saveWindowGeometry()
WindowController::instance().saveGeometry();
}
void Controller::createRoom(const QString &name, const QString &topic)
{
auto createRoomJob = m_connection->createRoom(Connection::PublishRoom, QString(), name, topic, QStringList());
connect(createRoomJob, &CreateRoomJob::failure, this, [this, createRoomJob] {
Q_EMIT errorOccured(i18n("Room creation failed: %1", createRoomJob->errorString()));
});
connectSingleShot(this, &Controller::roomAdded, &RoomManager::instance(), &RoomManager::enterRoom, Qt::QueuedConnection);
}
void Controller::createSpace(const QString &name, const QString &topic)
{
auto createRoomJob = m_connection->createRoom(Connection::UnpublishRoom,
{},
name,
topic,
QStringList(),
{},
{},
false,
{},
{},
QJsonObject{
{"type"_ls, "m.space"_ls},
});
connect(createRoomJob, &CreateRoomJob::failure, this, [this, createRoomJob] {
Q_EMIT errorOccured(i18n("Space creation failed: %1", createRoomJob->errorString()));
});
connectSingleShot(this, &Controller::roomAdded, &RoomManager::instance(), &RoomManager::enterRoom, Qt::QueuedConnection);
}
bool Controller::isOnline() const
{
return m_isOnline;

View File

@@ -113,6 +113,16 @@ public:
*/
bool saveAccessTokenToKeyChain(const Quotient::AccountSettings &account, const QByteArray &accessToken);
/**
* @brief Create new room for a group chat.
*/
Q_INVOKABLE void createRoom(const QString &name, const QString &topic);
/**
* @brief Create new space.
*/
Q_INVOKABLE void createSpace(const QString &name, const QString &topic);
/**
* @brief Join a room.
*/
@@ -206,6 +216,7 @@ Q_SIGNALS:
void userConsentRequired(QUrl url);
void isOnlineChanged(bool isOnline);
void activeConnectionIndexChanged();
void roomAdded(NeoChatRoom *room);
public Q_SLOTS:
void saveWindowGeometry();

View File

@@ -93,9 +93,4 @@ void LinkPreviewer::loadUrlPreview()
}
}
bool LinkPreviewer::empty() const
{
return m_url.isEmpty();
}
#include "moc_linkpreviewer.cpp"

View File

@@ -44,13 +44,6 @@ class LinkPreviewer : public QObject
*/
Q_PROPERTY(QUrl imageSource READ imageSource NOTIFY imageSourceChanged)
/**
* @brief Whether the there is a link to preview.
*
* A linkPreviwer is empty if the URL is empty.
*/
Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged)
public:
explicit LinkPreviewer(QObject *parent = nullptr, const NeoChatRoom *room = nullptr, const QUrl &url = {});
@@ -60,7 +53,6 @@ public:
[[nodiscard]] QString title() const;
[[nodiscard]] QString description() const;
[[nodiscard]] QUrl imageSource() const;
[[nodiscard]] bool empty() const;
private:
const NeoChatRoom *m_currentRoom = nullptr;
@@ -79,6 +71,5 @@ Q_SIGNALS:
void descriptionChanged();
void imageSourceChanged();
void urlChanged();
void emptyChanged();
};
Q_DECLARE_METATYPE(LinkPreviewer *)

View File

@@ -107,8 +107,6 @@
#include <Windows.h>
#endif
#include "messageformatter.h"
using namespace Quotient;
class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
@@ -230,12 +228,6 @@ int main(int argc, char *argv[])
Login *login = new Login();
UrlHelper urlHelper;
MessageFormatter formatter;
// formatter.formatInternal("<p>hrrejoire</p>\n<pre><code class=\"language-js\">var i = 0; i++; function\n</code></pre>\n<p>rekore</p>\n", new
// QTextDocument);
// return 0;
#ifdef HAVE_COLORSCHEME
ColorSchemer colorScheme;
qmlRegisterSingletonInstance<ColorSchemer>("org.kde.neochat", 1, 0, "ColorSchemer", &colorScheme);
@@ -244,7 +236,6 @@ int main(int argc, char *argv[])
}
#endif
qmlRegisterSingletonInstance<MessageFormatter>("org.kde.neochat", 1, 0, "MessageFormatter", &formatter);
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "Controller", &Controller::instance());
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "NotificationsManager", &NotificationsManager::instance());
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "Clipboard", &clipboard);

View File

@@ -1,133 +0,0 @@
// SPDX-FileCopyrightText: 2021 Carson Black <uhhadd@gmail.com>
// SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "messageformatter.h"
#include <QDomDocument>
#include <QGuiApplication>
#include <QPalette>
#include <QQmlContext>
#include <QQmlProperty>
#include <QTextCursor>
#include <QTextDocumentFragment>
#include <KSyntaxHighlighting/definition.h>
#include <KSyntaxHighlighting/repository.h>
#include <KSyntaxHighlighting/syntaxhighlighter.h>
#include <KSyntaxHighlighting/theme.h>
QTextDocumentFragment copyTextLayoutFrom(QTextDocument *document)
{
QTextCursor sourceCursor(document);
sourceCursor.select(QTextCursor::Document);
QTextDocument helper;
// copy the content fragment from the source document into our helper document
QTextCursor curs(&helper);
curs.insertFragment(sourceCursor.selection());
curs.select(QTextCursor::Document);
// not sure why, but fonts get lost. since this is for codeblocks, we can
// just force the mono font. anyone copying this code would probably want
// to fix the problem proper if it's not also for codeblocks.
const auto fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
const int docStart = sourceCursor.selectionStart();
const int docEnd = helper.characterCount() - 1;
// since the copied fragment above lost the qsyntaxhighlighter stuff,
// we gotta go through the qtextlayout and apply those styles to the
// document
const auto end = document->findBlock(sourceCursor.selectionEnd()).next();
for (auto current = document->findBlock(docStart); current.isValid() && current != end; current = current.next()) {
const auto layout = current.layout();
// iterate through the formats, applying them to our document
for (const auto &span : layout->formats()) {
const int start = current.position() + span.start - docStart;
const int end = start + span.length;
curs.setPosition(qMax(start, 0));
curs.setPosition(qMin(end, docEnd), QTextCursor::KeepAnchor);
auto fmt = span.format;
fmt.setFont(fixedFont);
curs.setCharFormat(fmt);
}
}
return QTextDocumentFragment(&helper);
}
QTextDocumentFragment highlight(const QString &code, const QString &language)
{
using namespace KSyntaxHighlighting;
static Repository repo;
auto theme = repo.themeForPalette(QGuiApplication::palette());
auto definition = repo.definitionForFileName(QLatin1String("file.") + language);
QTextDocument doku(code);
QScopedPointer<SyntaxHighlighter> highlighter(new SyntaxHighlighter(&doku));
highlighter->setTheme(theme);
highlighter->setDefinition(definition);
return copyTextLayoutFrom(&doku);
}
bool extractCodeBlock(QTextCursor cursor, QDomElement element)
{
const auto codeNode = element.firstChild();
if (!codeNode.isNull()) {
const auto code = codeNode.toElement();
if (!code.isNull() && code.tagName() == QLatin1String("code")) {
QString lang;
auto langClass = code.attribute(QLatin1String("class"), QLatin1String("none"));
if (langClass != QLatin1String("none") && langClass.startsWith(QLatin1String("language-"))) {
lang = langClass.remove(0, 9);
}
if (!lang.isNull()) {
cursor.insertFragment(highlight(code.text(), lang));
return true;
}
}
}
return false;
}
QString MessageFormatter::formatInternal(const QString &messageBody, QTextDocument *document)
{
QTextCursor curs(document);
QDomDocument doc(QLatin1String("htmlement"));
doc.setContent(QStringLiteral("<div>%1</div>").arg(messageBody));
QDomElement docElem = doc.documentElement();
QDomNode n = docElem.firstChild();
while (!n.isNull()) {
QDomElement e = n.toElement();
if (!e.isNull()) {
if (e.tagName() != QLatin1String("pre") || !extractCodeBlock(curs, e)) {
QString outText;
QTextStream out(&outText);
e.save(out, 0);
curs.insertHtml(outText);
}
}
n = n.nextSibling();
}
Q_EMIT document->contentsChanged();
return document->toHtml();
}
QString MessageFormatter::format(const QString &messageBody, QQuickTextDocument *doc, QQuickItem *item)
{
QColor linkColor = QQmlProperty(item, QLatin1String("Kirigami.Theme.linkColor"), qmlContext(item)).read().value<QColor>();
return formatInternal(messageBody, doc->textDocument());
}

View File

@@ -1,13 +0,0 @@
// SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QQuickItem>
#include <QQuickTextDocument>
class MessageFormatter : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE QString format(const QString &messageBody, QQuickTextDocument *doc, QQuickItem *item);
Q_INVOKABLE QString formatInternal(const QString &messageBody, QTextDocument *doc);
};

View File

@@ -36,13 +36,13 @@ RoomListModel::RoomListModel(QObject *parent)
m_categoryVisibility[collapsedSection] = false;
}
connect(this, &RoomListModel::highlightCountChanged, this, [this]() {
connect(this, &RoomListModel::notificationCountChanged, this, [this]() {
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
#ifndef Q_OS_ANDROID
// copied from Telegram desktop
const auto launcherUrl = "application://org.kde.neochat.desktop"_ls;
// Gnome requires that count is a 64bit integer
const qint64 counterSlice = std::min(m_highlightCount, 9999);
const qint64 counterSlice = std::min(m_notificationCount, 9999);
QVariantMap dbusUnityProperties;
if (counterSlice > 0) {
@@ -59,7 +59,7 @@ RoomListModel::RoomListModel(QObject *parent)
QDBusConnection::sessionBus().send(signal);
#endif // Q_OS_ANDROID
#else
qGuiApp->setBadgeNumber(m_highlightCount);
qGuiApp->setBadgeNumber(m_notificationCount);
#endif // QT_VERSION_CHECK(6, 6, 0)
});
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() {
@@ -144,6 +144,7 @@ void RoomListModel::doAddRoom(Room *r)
m_rooms.append(room);
connectRoomSignals(room);
Q_EMIT roomAdded(room);
Q_EMIT Controller::instance().roomAdded(room);
} else {
qCritical() << "Attempt to add nullptr to the room list";
Q_ASSERT(false);
@@ -161,9 +162,6 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room)
connect(room, &Room::notificationCountChanged, this, [this, room] {
refresh(room);
});
connect(room, &Room::highlightCountChanged, this, [this, room] {
refresh(room);
});
connect(room, &Room::avatarChanged, this, [this, room] {
refresh(room, {AvatarRole});
});
@@ -180,7 +178,6 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room)
refresh(room, {LastEventRole, SubtitleTextRole});
});
connect(room, &Room::unreadStatsChanged, this, &RoomListModel::refreshNotificationCount);
connect(room, &Room::highlightCountChanged, this, &RoomListModel::refreshHighlightCount);
}
int RoomListModel::notificationCount() const
@@ -188,11 +185,6 @@ int RoomListModel::notificationCount() const
return m_notificationCount;
}
int RoomListModel::highlightCount() const
{
return m_highlightCount;
}
void RoomListModel::refreshNotificationCount()
{
int count = 0;
@@ -206,19 +198,6 @@ void RoomListModel::refreshNotificationCount()
Q_EMIT notificationCountChanged();
}
void RoomListModel::refreshHighlightCount()
{
int count = 0;
for (auto room : std::as_const(m_rooms)) {
count += room->highlightCount();
}
if (m_highlightCount == count) {
return;
}
m_highlightCount = count;
Q_EMIT highlightCountChanged();
}
void RoomListModel::updateRoom(Room *room, Room *prev)
{
// There are two cases when this method is called:

View File

@@ -85,7 +85,6 @@ public:
void setConnection(Quotient::Connection *connection);
[[nodiscard]] int notificationCount() const;
[[nodiscard]] int highlightCount() const;
/**
* @brief Get the given role value at the given index.
@@ -156,7 +155,6 @@ private Q_SLOTS:
void deleteRoom(Quotient::Room *room);
void refresh(NeoChatRoom *room, const QVector<int> &roles = {});
void refreshNotificationCount();
void refreshHighlightCount();
private:
Quotient::Connection *m_connection = nullptr;
@@ -165,7 +163,6 @@ private:
QMap<int, bool> m_categoryVisibility;
int m_notificationCount = 0;
int m_highlightCount = 0;
QString m_activeSpaceId;
void connectRoomSignals(NeoChatRoom *room);
@@ -173,7 +170,6 @@ private:
Q_SIGNALS:
void connectionChanged();
void notificationCountChanged();
void highlightCountChanged();
void roomAdded(NeoChatRoom *_t1);
};

View File

@@ -8,7 +8,6 @@
#include "controller.h"
#include "jobs/neochatchangepasswordjob.h"
#include "jobs/neochatdeactivateaccountjob.h"
#include "roommanager.h"
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <qt5keychain/keychain.h>
@@ -16,11 +15,8 @@
#include <qt6keychain/keychain.h>
#endif
#include <KLocalizedString>
#include <Quotient/csapi/content-repo.h>
#include <Quotient/csapi/profile.h>
#include <Quotient/qt_connection_util.h>
#include <Quotient/settings.h>
#include <Quotient/user.h>
@@ -160,26 +156,4 @@ void NeoChatConnection::deactivateAccount(const QString &password)
});
}
void NeoChatConnection::createRoom(const QString &name, const QString &topic)
{
const auto job = Connection::createRoom(Connection::PublishRoom, {}, name, topic, {});
connect(job, &CreateRoomJob::failure, this, [this, job] {
Q_EMIT Controller::instance().errorOccured(i18n("Room creation failed: %1", job->errorString()));
});
connectSingleShot(this, &Connection::newRoom, this, [](Room *room) {
RoomManager::instance().enterRoom(dynamic_cast<NeoChatRoom *>(room));
});
}
void NeoChatConnection::createSpace(const QString &name, const QString &topic)
{
const auto job = Connection::createRoom(Connection::UnpublishRoom, {}, name, topic, {}, {}, {}, false, {}, {}, QJsonObject{{"type"_ls, "m.space"_ls}});
connect(job, &CreateRoomJob::failure, this, [this, job] {
Q_EMIT Controller::instance().errorOccured(i18n("Space creation failed: %1", job->errorString()));
});
connectSingleShot(this, &Connection::newRoom, this, [](Room *room) {
RoomManager::instance().enterRoom(dynamic_cast<NeoChatRoom *>(room));
});
}
#include "moc_neochatconnection.cpp"

View File

@@ -48,16 +48,6 @@ public:
Q_INVOKABLE void deactivateAccount(const QString &password);
/**
* @brief Create new room for a group chat.
*/
Q_INVOKABLE void createRoom(const QString &name, const QString &topic);
/**
* @brief Create new space.
*/
Q_INVOKABLE void createSpace(const QString &name, const QString &topic);
Q_SIGNALS:
void labelChanged();
};

View File

@@ -357,26 +357,38 @@ QQC2.Control {
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered
}
RowLayout {
Row {
id: actionsRow
padding: Kirigami.Units.smallSpacing
spacing: Kirigami.Units.smallSpacing
anchors.right: parent.right
anchors.bottom: parent.bottom
property var requiredMargin: (root.width - chatBarSizeHelper.currentWidth) / 2 + Kirigami.Units.largeSpacing + (chatBarScrollView.QQC2.ScrollBar.vertical.visible && !(root.width > chatBarSizeHelper.currentWidth) ? Kirigami.Units.largeSpacing * 2.5 : 0)
anchors.leftMargin: layoutDirection === Qt.RightToLeft ? requiredMargin : 0
anchors.rightMargin: layoutDirection === Qt.RightToLeft ? 0 : requiredMargin
anchors.bottomMargin: Kirigami.Units.smallSpacing
spacing: 0
property var requiredMargin: (root.width - chatBarSizeHelper.currentWidth) / 2 + Kirigami.Units.largeSpacing + (chatBarScrollView.QQC2.ScrollBar.vertical.visible && !(root.width > chatBarSizeHelper.currentWidth) ? Kirigami.Units.largeSpacing * 2.5 : 0)
anchors.bottom: parent.bottom
anchors.bottomMargin: Kirigami.Units.largeSpacing - 2
Repeater {
model: root.actions
delegate: QQC2.ToolButton {
Layout.alignment: Qt.AlignVCenter
icon.name: modelData.isBusy ? "" : (modelData.icon.name.length > 0 ? modelData.icon.name : modelData.icon.source)
onClicked: modelData.trigger()
Kirigami.Icon {
implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium
QQC2.ToolTip.visible: hovered
source: modelData.isBusy ? "" : (modelData.icon.name.length > 0 ? modelData.icon.name : modelData.icon.source)
active: actionArea.containsPress
visible: modelData.visible
enabled: modelData.enabled
MouseArea {
id: actionArea
anchors.fill: parent
onClicked: modelData.trigger()
cursorShape: Qt.PointingHandCursor
}
QQC2.ToolTip.visible: modelData.tooltip !== "" && hoverHandler.hovered
QQC2.ToolTip.text: modelData.tooltip
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
HoverHandler { id: hoverHandler }
PieProgressBar {
visible: modelData.isBusy

View File

@@ -14,7 +14,7 @@ import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
import org.kde.neochat 1.0
QQC2.Popup {
id: root
id: completionMenu
width: parent.width
visible: completions.count > 0
@@ -38,7 +38,7 @@ QQC2.Popup {
}
function complete() {
root.chatDocumentHandler.complete(completions.currentIndex)
completionMenu.chatDocumentHandler.complete(completions.currentIndex)
}
leftPadding: 0
@@ -52,7 +52,7 @@ QQC2.Popup {
id: completions
anchors.fill: parent
model: root.chatDocumentHandler.completionModel
model: completionMenu.chatDocumentHandler.completionModel
currentIndex: 0
keyNavigationWraps: true
highlightMoveDuration: 100
@@ -81,7 +81,7 @@ QQC2.Popup {
subtitleItem.textFormat: Text.PlainText
}
}
onClicked: root.chatDocumentHandler.complete(completionDelegate.index)
onClicked: completionMenu.chatDocumentHandler.complete(completionDelegate.index)
}
}

View File

@@ -6,15 +6,15 @@ import QtQuick.Controls 2.15 as QQC2
import org.kde.kirigami 2.20 as Kirigami
QQC2.ItemDelegate {
id: root
id: emojiDelegate
property string name
property string emoji
property bool showTones: false
property bool isImage: false
QQC2.ToolTip.text: root.name
QQC2.ToolTip.visible: hovered && root.name !== ""
QQC2.ToolTip.text: emojiDelegate.name
QQC2.ToolTip.visible: hovered && emojiDelegate.name !== ""
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
leftInset: Kirigami.Units.smallSpacing
topInset: Kirigami.Units.smallSpacing
@@ -24,8 +24,8 @@ QQC2.ItemDelegate {
contentItem: Item {
Kirigami.Heading {
anchors.fill: parent
visible: !root.emoji.startsWith("image") && !root.isImage
text: root.emoji
visible: !emojiDelegate.emoji.startsWith("image") && !emojiDelegate.isImage
text: emojiDelegate.emoji
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.family: "emoji"
@@ -36,25 +36,25 @@ QQC2.ItemDelegate {
source: "arrow-down"
anchors.bottom: parent.bottom
anchors.right: parent.right
visible: root.showTones
visible: emojiDelegate.showTones
}
}
Image {
anchors.fill: parent
visible: root.emoji.startsWith("image") || root.isImage
source: visible ? root.emoji : ""
visible: emojiDelegate.emoji.startsWith("image") || emojiDelegate.isImage
source: visible ? emojiDelegate.emoji : ""
}
}
background: Rectangle {
color: root.checked ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
color: emojiDelegate.checked ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
radius: Kirigami.Units.smallSpacing
Rectangle {
radius: Kirigami.Units.smallSpacing
anchors.fill: parent
color: Kirigami.Theme.highlightColor
opacity: root.hovered && !root.pressed ? 0.2 : 0
opacity: emojiDelegate.hovered && !emojiDelegate.pressed ? 0.2 : 0
}
}
}

View File

@@ -7,7 +7,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
QQC2.ScrollView {
id: root
id: emojiGrid
property alias model: emojis.model
property alias count: emojis.count
@@ -40,10 +40,10 @@ QQC2.ScrollView {
}
onModelChanged: currentIndex = -1
cellWidth: emojis.width / root.emojisPerRow
cellHeight: root.targetIconSize
cellWidth: emojis.width / emojiGrid.emojisPerRow
cellHeight: emojiGrid.targetIconSize
KeyNavigation.up: root.header
KeyNavigation.up: emojiGrid.header
clip: true
@@ -56,14 +56,14 @@ QQC2.ScrollView {
width: emojis.cellWidth
height: emojis.cellHeight
isImage: root.stickers
isImage: emojiGrid.stickers
Keys.onEnterPressed: clicked()
Keys.onReturnPressed: clicked()
onClicked: {
if (root.stickers) {
root.stickerChosen(model.index)
if (emojiGrid.stickers) {
emojiGrid.stickerChosen(model.index)
}
root.chosen(modelData.isCustom ? modelData.shortName : modelData.unicode)
emojiGrid.chosen(modelData.isCustom ? modelData.shortName : modelData.unicode)
EmojiModel.emojiUsed(modelData)
}
Keys.onSpacePressed: pressAndHold()
@@ -71,7 +71,7 @@ QQC2.ScrollView {
if (EmojiModel.tones(modelData.shortName).length === 0) {
return;
}
let tones = tonesPopupComponent.createObject(emojiDelegate, {shortName: modelData.shortName, unicode: modelData.unicode, categoryIconSize: root.targetIconSize})
let tones = tonesPopupComponent.createObject(emojiDelegate, {shortName: modelData.shortName, unicode: modelData.unicode, categoryIconSize: emojiGrid.targetIconSize})
tones.open()
tones.forceActiveFocus()
}
@@ -80,14 +80,14 @@ QQC2.ScrollView {
Kirigami.PlaceholderMessage {
anchors.centerIn: parent
text: root.stickers ? i18n("No stickers") : i18n("No emojis")
text: emojiGrid.stickers ? i18n("No stickers") : i18n("No emojis")
visible: emojis.count === 0
}
}
Component {
id: tonesPopupComponent
EmojiTonesPicker {
onChosen: root.chosen(emoji)
onChosen: emojiGrid.chosen(emoji)
}
}
}

View File

@@ -8,7 +8,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
QQC2.Popup {
id: root
id: tones
signal chosen(string emoji)
@@ -20,14 +20,14 @@ QQC2.Popup {
required property string shortName
required property string unicode
required property int categoryIconSize
width: root.categoryIconSize * tonesList.count + 2 * padding
height: root.categoryIconSize + 2 * padding
width: tones.categoryIconSize * tonesList.count + 2 * padding
height: tones.categoryIconSize + 2 * padding
y: -height
padding: 2
modal: true
dim: true
clip: false
onOpened: x = Math.min(parent.mapFromGlobal(QQC2.Overlay.overlay.width - root.width, 0).x, -(width - parent.width) / 2)
onOpened: x = Math.min(parent.mapFromGlobal(QQC2.Overlay.overlay.width - tones.width, 0).x, -(width - parent.width) / 2)
background: Kirigami.ShadowedRectangle {
color: Kirigami.Theme.backgroundColor
radius: Kirigami.Units.mediumSpacing
@@ -47,7 +47,7 @@ QQC2.Popup {
width: parent.width
height: parent.height
orientation: Qt.Horizontal
model: EmojiModel.tones(root.shortName)
model: EmojiModel.tones(tones.shortName)
keyNavigationEnabled: true
keyNavigationWraps: true
@@ -57,15 +57,15 @@ QQC2.Popup {
emoji: modelData.unicode
name: modelData.shortName
width: root.categoryIconSize
width: tones.categoryIconSize
height: width
Keys.onEnterPressed: clicked()
Keys.onReturnPressed: clicked()
onClicked: {
root.chosen(modelData.unicode)
tones.chosen(modelData.unicode)
EmojiModel.emojiUsed(modelData)
root.close()
tones.close()
}
}
}

View File

@@ -8,7 +8,7 @@ import QtQuick.Particles 2.15
import org.kde.kirigami 2.15 as Kirigami
Item {
id: root
id: item
property bool enabled: false
property int effectInterval: Kirigami.Units.veryLongDuration*10;
property color darkSnowColor: "grey"
@@ -30,12 +30,12 @@ Item {
Timer {
id: confettiTimer
interval: root.effectInterval;
interval: item.effectInterval;
running: false;
repeat: false;
triggeredOnStart: true;
onTriggered: {
if (root.enabled) {
if (item.enabled) {
confettiSystem.running = !confettiSystem.running
}
}
@@ -92,12 +92,12 @@ Item {
Timer {
id: snowTimer
interval: root.effectInterval;
interval: item.effectInterval;
running: false;
repeat: false;
triggeredOnStart: true;
onTriggered: {
if (root.enabled) {
if (item.enabled) {
snowSystem.running = !snowSystem.running
}
}
@@ -127,7 +127,7 @@ Item {
width: 10
height: width
radius: width
color: root.isThemeDark ? "white" : darkSnowColor
color: item.isThemeDark ? "white" : darkSnowColor
scale: Math.random()
opacity: Math.random()
}
@@ -157,12 +157,12 @@ Item {
Timer {
id: fireworksTimer
interval: root.effectInterval;
interval: item.effectInterval;
running: false;
repeat: false;
triggeredOnStart: true;
onTriggered: {
if (root.enabled) {
if (item.enabled) {
fireworksInternalTimer.running = !fireworksInternalTimer.running
}
}
@@ -206,8 +206,8 @@ Item {
id: fireworksParticleA
system: fireworksSystem
source: "qrc:/glowdot.png"
alphaVariation: root.isThemeDark ? 0.1 : 0.1
alpha: root.isThemeDark ? 0.5 : 1
alphaVariation: item.isThemeDark ? 0.1 : 0.1
alpha: item.isThemeDark ? 0.5 : 1
groups: ["a"]
opacity: fireworksSystem.opacity
entryEffect: ImageParticle.Scale
@@ -217,9 +217,9 @@ Item {
ImageParticle {
system: fireworksSystem
source: "qrc:/glowdot.png"
color: root.isThemeDark ? "white" : "gold"
alphaVariation: root.isThemeDark ? 0.1 : 0.1
alpha: root.isThemeDark ? 0.5 : 1
color: item.isThemeDark ? "white" : "gold"
alphaVariation: item.isThemeDark ? 0.1 : 0.1
alpha: item.isThemeDark ? 0.5 : 1
groups: ["light"]
opacity: fireworksSystem.opacity
entryEffect: ImageParticle.Scale
@@ -230,8 +230,8 @@ Item {
id: fireworksParticleB
system: fireworksSystem
source: "qrc:/glowdot.png"
alphaVariation: root.isThemeDark ? 0.1 : 0.1
alpha: root.isThemeDark ? 0.5 : 1
alphaVariation: item.isThemeDark ? 0.1 : 0.1
alpha: item.isThemeDark ? 0.5 : 1
groups: ["b"]
opacity: fireworksSystem.opacity
entryEffect: ImageParticle.Scale
@@ -257,7 +257,7 @@ Item {
onTriggered: {
container.destroy();
var randomHue = Math.random()
var lightness = root.isThemeDark ? 0.8 : 0.7
var lightness = item.isThemeDark ? 0.8 : 0.7
fireworksParticleA.color = Qt.hsla(randomHue, 0.8, lightness, 1)
fireworksParticleB.color = Qt.hsla(1-randomHue, 0.8, lightness, 1)
}

View File

@@ -9,7 +9,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
Kirigami.Page {
id: root
id: locationsPage
required property var room
@@ -31,7 +31,7 @@ Kirigami.Page {
MapItemView {
model: LocationsModel {
id: locationsModel
room: root.room
room: locationsPage.room
}
delegate: LocationMapItem {
isLive: true
@@ -42,7 +42,7 @@ Kirigami.Page {
MapItemView {
model: LiveLocationsModel {
id: liveLocationsModel
room: root.room
room: locationsPage.room
}
delegate: LocationMapItem {}
}

View File

@@ -8,7 +8,7 @@ import QtQuick 2.15
import org.kde.kirigami 2.15 as Kirigami
Gradient {
id: root
id: gradient
orientation: Gradient.Horizontal
@@ -25,7 +25,7 @@ Gradient {
from: -2.0
to: 2.0
duration: 700
target: root
target: gradient
properties: "pos"
}
PauseAnimation {
@@ -33,7 +33,7 @@ Gradient {
}
}
GradientStop { position: root.pos-root.offset; color: root.translucent }
GradientStop { position: root.pos; color: root.bright }
GradientStop { position: root.pos+root.offset; color: root.translucent }
}
GradientStop { position: gradient.pos-gradient.offset; color: gradient.translucent }
GradientStop { position: gradient.pos; color: gradient.bright }
GradientStop { position: gradient.pos+gradient.offset; color: gradient.translucent }
}

View File

@@ -23,7 +23,7 @@ Loader {
* - description - the description of the URL preview.
* - imageSource - a source URL for the preview image.
*/
required property var linkPreviewer
property var linkPreviewer
/**
* @brief Standard height for the link preview.
@@ -39,7 +39,7 @@ Loader {
property bool indicatorEnabled: false
visible: active
sourceComponent: linkPreviewer && linkPreviewer.loaded ? linkPreviewComponent : loadingComponent
sourceComponent: linkPreviewer.loaded ? linkPreviewComponent : loadingComponent
Component {
id: linkPreviewComponent
@@ -61,10 +61,10 @@ Loader {
color: Kirigami.Theme.highlightColor
}
Image {
visible: root.linkPreviewer.imageSource
visible: linkPreviewer.imageSource
Layout.maximumHeight: root.defaultHeight
Layout.maximumWidth: root.defaultHeight
source: root.linkPreviewer.imageSource
source: linkPreviewer.imageSource
fillMode: Image.PreserveAspectFit
}
ColumnLayout {
@@ -108,7 +108,7 @@ Loader {
id: maximizeButton
anchors.right: parent.right
anchors.bottom: parent.bottom
visible: componentRoot.hovered && (componentRoot.truncated || checked)
visible: false
checkable: true
icon.name: checked ? "go-up" : "go-down"

View File

@@ -68,7 +68,7 @@ TimelineContainer {
}
LinkPreviewDelegate {
Layout.fillWidth: true
active: !currentRoom.usesEncryption && currentRoom.urlPreviewEnabled && Config.showLinkPreview && root.showLinkPreview && !root.linkPreview.empty
active: !currentRoom.usesEncryption && currentRoom.urlPreviewEnabled && Config.showLinkPreview && root.showLinkPreview
linkPreviewer: root.linkPreview
indicatorEnabled: root.isVisibleInTimeline()
}

View File

@@ -11,8 +11,7 @@ import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
QQC2.ItemDelegate {
id: root
id: readMarkerDelegate
padding: Kirigami.Units.largeSpacing
topInset: Kirigami.Units.largeSpacing
topPadding: Kirigami.Units.largeSpacing * 2
@@ -42,7 +41,7 @@ QQC2.ItemDelegate {
State {
name: "alignLeft"
AnchorChanges {
target: root
target: readMarkerDelegate
anchors.horizontalCenter: undefined
anchors.left: parent ? parent.left : undefined
}
@@ -50,7 +49,7 @@ QQC2.ItemDelegate {
State {
name: "alignCenter"
AnchorChanges {
target: root
target: readMarkerDelegate
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
anchors.left: undefined
}
@@ -73,7 +72,7 @@ QQC2.ItemDelegate {
background: Kirigami.ShadowedRectangle {
id: readMarkerBackground
color: {
if (root.isTemporaryHighlighted) {
if (readMarkerDelegate.isTemporaryHighlighted) {
return Kirigami.Theme.positiveBackgroundColor
} else {
return Kirigami.Theme.backgroundColor
@@ -81,7 +80,7 @@ QQC2.ItemDelegate {
}
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.View
opacity: root.isTemporaryHighlighted ? 1 : 0.6
opacity: readMarkerDelegate.isTemporaryHighlighted ? 1 : 0.6
radius: Kirigami.Units.smallSpacing
shadow.size: Kirigami.Units.smallSpacing
shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.10)

View File

@@ -44,7 +44,6 @@ TextEdit {
property bool spoilerRevealed: !hasSpoiler.test(textMessage)
ListView.onReused: Qt.binding(() => !hasSpoiler.test(textMessage))
onTextMessageChanged: text = MessageFormatter.format(textMessage, contentLabel.textDocument, contentLabel)
persistentSelection: true
@@ -53,7 +52,6 @@ TextEdit {
Controller.forceRefreshTextDocument(root.textDocument, root)
}
/*
text: "<style>
table {
width:100%;
@@ -86,11 +84,7 @@ a{
background: " + Kirigami.Theme.textColor + ";
}
" : "") + "
<<<<<<< HEAD:src/qml/Component/Timeline/RichLabel.qml
</style>" + textMessage
=======
</style>" + (isEmote ? "* <a href='https://matrix.to/#/" + author.id + "' style='color: " + author.color + "'>" + author.displayName + "</a> " : "") + textMessage + (isEdited ? (" <span style=\"color: " + Kirigami.Theme.disabledTextColor + "\">" + "<span style='font-size: " + Kirigami.Theme.defaultFont.pixelSize +"px'>" + i18n(" (edited)") + "</span>") : "")
*/
color: Kirigami.Theme.textColor
selectedTextColor: Kirigami.Theme.highlightedTextColor
@@ -109,7 +103,7 @@ a{
RoomManager.openResource(link)
}
onHoveredLinkChanged: if (hoveredLink.length > 0 && hoveredLink !== "1") {
applicationWindow().hoverLinkIndicator.text = hoveredLink;
// applicationWindow().hoverLinkIndicator.text = hoveredLink;
} else {
applicationWindow().hoverLinkIndicator.text = "";
}

View File

@@ -11,7 +11,7 @@ import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
QQC2.ItemDelegate {
id: root
id: sectionDelegate
property alias labelText: sectionLabel.text
property var maxWidth: Number.POSITIVE_INFINITY
@@ -44,6 +44,6 @@ QQC2.ItemDelegate {
background: Rectangle {
color: Config.blur ? "transparent" : Kirigami.Theme.backgroundColor
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: root.colorSet
Kirigami.Theme.colorSet: sectionDelegate.colorSet
}
}

View File

@@ -11,7 +11,7 @@ import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
import org.kde.neochat 1.0
QQC2.Control {
id: root
id: stateDelegate
readonly property bool sectionVisible: model.showSection
@@ -23,7 +23,7 @@ QQC2.Control {
State {
name: "alignLeft"
AnchorChanges {
target: root
target: stateDelegate
anchors.horizontalCenter: undefined
anchors.left: parent ? parent.left : undefined
}
@@ -31,7 +31,7 @@ QQC2.Control {
State {
name: "alignCenter"
AnchorChanges {
target: root
target: stateDelegate
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
anchors.left: undefined
}
@@ -62,7 +62,6 @@ QQC2.Control {
Layout.fillWidth: true
visible: sectionVisible
labelText: sectionVisible ? section : ""
colorSet: Config.compactLayout ? Kirigami.Theme.View : Kirigami.Theme.Window
}
RowLayout {
Layout.fillWidth: true
@@ -204,6 +203,6 @@ QQC2.Control {
endPercentWidth: Config.compactLayout ? 100 : 85
maxWidth: Config.compactLayout ? -1 : Kirigami.Units.gridUnit * 60
parentWidth: root.parent ? root.parent.width : 0
parentWidth: stateDelegate.parent ? stateDelegate.parent.width : 0
}
}

View File

@@ -550,11 +550,7 @@ ColumnLayout {
}
}
background: Rectangle {
visible: mainContainer.hovered && (Config.compactLayout || root.alwaysMaxWidth)
color: Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15)
radius: Kirigami.Units.smallSpacing
}
background: Item {}
TapHandler {
acceptedDevices: PointerDevice.Mouse

View File

@@ -116,7 +116,6 @@ QQC2.ScrollView {
z: 3
visible: !!messageListView.sectionBannerItem && messageListView.sectionBannerItem.ListView.section !== "" && !Config.blur
labelText: messageListView.sectionBannerItem ? messageListView.sectionBannerItem.ListView.section : ""
colorSet: Config.compactLayout ? Kirigami.Theme.View : Kirigami.Theme.Window
}
footerPositioning: ListView.OverlayHeader
@@ -239,7 +238,8 @@ QQC2.ScrollView {
width: delegate ? delegate.bubbleWidth : Kirigami.Units.gridUnit * 4
currentRoom: root.currentRoom
showActions: delegate && delegate.hovered
visible: false
showActions: false
verified: delegate && delegate.verified
editable: delegate && delegate.author.isLocalUser && (delegate.delegateType === DelegateType.Emote || delegate.delegateType === DelegateType.Message)

View File

@@ -10,7 +10,7 @@ import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
QQC2.Dialog {
id: root
id: confirmEncryptionDialog
property NeoChatRoom room
@@ -31,15 +31,15 @@ QQC2.Dialog {
QQC2.Button {
text: i18n("Cancel")
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
onClicked: root.close()
onClicked: confirmEncryptionDialog.close()
}
QQC2.Button {
text: i18n("Activate Encryption")
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
onClicked: {
root.room.activateEncryption()
root.close();
confirmEncryptionDialog.room.activateEncryption()
confirmEncryptionDialog.close();
}
}
}

View File

@@ -12,8 +12,6 @@ FormCard.FormCardPage {
title: i18nc("@title", "Create a Room")
required property NeoChatConnection connection
Component.onCompleted: roomNameField.forceActiveFocus()
FormCard.FormHeader {
@@ -37,7 +35,7 @@ FormCard.FormCardPage {
text: i18nc("@action:button", "Ok")
enabled: roomNameField.text.length > 0
onClicked: {
root.connection.createRoom(roomNameField.text, roomTopicField.text);
Controller.createRoom(roomNameField.text, roomTopicField.text);
root.closeDialog()
}
}

View File

@@ -11,8 +11,6 @@ import org.kde.kirigamiaddons.formcard 1.0 as FormCard
FormCard.FormCardPage {
id: root
required property NeoChatConnection connection
title: i18n("Create a Space")
Kirigami.Theme.colorSet: Kirigami.Theme.Window
@@ -32,7 +30,7 @@ FormCard.FormCardPage {
FormCard.FormButtonDelegate {
text: i18n("Create space")
onClicked: {
root.connection.createSpace(nameDelegate.text, topicDelegate.text)
Controller.createSpace(nameDelegate.text, topicDelegate.text)
root.close()
root.destroy()
}

View File

@@ -9,7 +9,7 @@ import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
QQC2.Popup {
id: root
id: emojiPopup
/**
* @brief The current room that user is viewing.
@@ -25,7 +25,7 @@ QQC2.Popup {
Connections {
target: RoomManager
function onCurrentRoomChanged() {
root.close()
emojiPopup.close()
}
}
@@ -64,11 +64,11 @@ QQC2.Popup {
id: emojiPicker
height: 400
currentRoom: root.currentRoom
includeCustom: root.includeCustom
showQuickReaction: root.showQuickReaction
includeCustom: emojiPopup.includeCustom
showQuickReaction: emojiPopup.showQuickReaction
onChosen: emoji => {
root.chosen(emoji)
if (root.closeOnChosen) root.close()
emojiPopup.chosen(emoji)
if (emojiPopup.closeOnChosen) emojiPopup.close()
}
}
}

View File

@@ -9,7 +9,7 @@ import org.kde.kirigami 2.19 as Kirigami
import org.kde.neochat 1.0
Column {
id: root
id: emojiItem
property string emoji
property string description
@@ -23,7 +23,7 @@ Column {
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: root.emoji
text: emojiItem.emoji
font.family: "emoji"
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 4
}
@@ -32,7 +32,7 @@ Column {
y: parent.height * 0.75
width: parent.width
height: parent.height * 0.25
text: root.description
text: emojiItem.description
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}

View File

@@ -7,7 +7,7 @@ import QtQml 2.15
import org.kde.neochat 1.0
Row {
id: root
id: emojiRow
property alias model: repeater.model
anchors.horizontalCenter: parent.horizontalCenter
@@ -16,7 +16,7 @@ Row {
delegate: EmojiItem {
emoji: modelData.emoji
description: modelData.description
width: root.height
width: emojiRow.height
height: width
}
}

View File

@@ -9,7 +9,7 @@ import org.kde.kirigami 2.19 as Kirigami
import org.kde.neochat 1.0
Column {
id: root
id: emojiSas
required property var model
@@ -25,12 +25,12 @@ Column {
EmojiRow {
anchors.horizontalCenter: parent.horizontalCenter
height: Kirigami.Units.gridUnit * 4
model: root.model.slice(0, 4)
model: emojiSas.model.slice(0, 4)
}
EmojiRow {
anchors.horizontalCenter: parent.horizontalCenter
height: Kirigami.Units.gridUnit * 4
model: root.model.slice(4, 7)
model: emojiSas.model.slice(4, 7)
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
@@ -38,13 +38,13 @@ Column {
anchors.bottom: parent.bottom
text: i18n("They match")
icon.name: "dialog-ok"
onClicked: root.accept()
onClicked: emojiSas.accept()
}
QQC2.Button {
anchors.bottom: parent.bottom
text: i18n("They don't match")
icon.name: "dialog-cancel"
onClicked: root.reject()
onClicked: emojiSas.reject()
}
}
}

View File

@@ -10,8 +10,7 @@ import org.kde.kirigami 2.19 as Kirigami
import org.kde.neochat 1.0
Kirigami.Page {
id: root
id: dialog
title: i18n("Session Verification")
required property var session
@@ -19,31 +18,31 @@ Kirigami.Page {
Item {
anchors.fill: parent
VerificationCanceled {
visible: root.session.state === KeyVerificationSession.CANCELED
visible: dialog.session.state === KeyVerificationSession.CANCELED
anchors.centerIn: parent
reason: root.session.error
reason: dialog.session.error
}
EmojiSas {
anchors.centerIn: parent
visible: root.session.state === KeyVerificationSession.WAITINGFORVERIFICATION
model: root.session.sasEmojis
onReject: root.session.cancelVerification(KeyVerificationSession.MISMATCHED_SAS)
onAccept: root.session.sendMac()
visible: dialog.session.state === KeyVerificationSession.WAITINGFORVERIFICATION
model: dialog.session.sasEmojis
onReject: dialog.session.cancelVerification(KeyVerificationSession.MISMATCHED_SAS)
onAccept: dialog.session.sendMac()
}
Message {
visible: root.session.state === KeyVerificationSession.WAITINGFORREADY
visible: dialog.session.state === KeyVerificationSession.WAITINGFORREADY
anchors.centerIn: parent
icon: "security-medium-symbolic"
text: i18n("Waiting for device to accept verification.")
}
Message {
visible: root.session.state === KeyVerificationSession.INCOMING
visible: dialog.session.state === KeyVerificationSession.INCOMING
anchors.centerIn: parent
icon: "security-medium-symbolic"
text: i18n("Incoming key verification request from device **%1**", root.session.remoteDeviceId)
text: i18n("Incoming key verification request from device **%1**", dialog.session.remoteDeviceId)
}
Message {
visible: root.session.state === KeyVerificationSession.WAITINGFORMAC
visible: dialog.session.state === KeyVerificationSession.WAITINGFORMAC
anchors.centerIn: parent
icon: "security-medium-symbolic"
text: i18n("Waiting for other party to verify.")
@@ -51,35 +50,35 @@ Kirigami.Page {
Kirigami.BasicListItem {
id: emojiVerification
text: "Emoji Verification"
visible: root.session.state === KeyVerificationSession.READY
visible: dialog.session.state === KeyVerificationSession.READY
subtitle: i18n("Compare a set of emoji on both devices")
onClicked: {
root.session.sendStartSas()
dialog.session.sendStartSas()
}
}
Message {
visible: root.session.state === KeyVerificationSession.DONE
visible: dialog.session.state === KeyVerificationSession.DONE
anchors.centerIn: parent
text: i18n("Successfully verified device **%1**", root.session.remoteDeviceId)
text: i18n("Successfully verified device **%1**", dialog.session.remoteDeviceId)
icon: "security-high"
}
}
footer: QQC2.ToolBar {
visible: root.session.state === KeyVerificationSession.INCOMING
visible: dialog.session.state === KeyVerificationSession.INCOMING
QQC2.DialogButtonBox {
anchors.fill: parent
Item { Layout.fillWidth: true }
QQC2.Button {
text: i18n("Accept")
icon.name: "dialog-ok"
onClicked: root.session.sendReady()
onClicked: dialog.session.sendReady()
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
}
QQC2.Button {
text: i18n("Decline")
icon.name: "dialog-cancel"
onClicked: root.session.cancelVerification("m.user", "Declined")
onClicked: dialog.session.cancelVerification("m.user", "Declined")
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
}
}

View File

@@ -9,8 +9,7 @@ import org.kde.kirigami 2.19 as Kirigami
import org.kde.neochat 1.0
Column {
id: root
id: message
required property string icon
required property string text
@@ -19,10 +18,10 @@ Column {
width: Kirigami.Units.iconSizes.enormous
height: width
anchors.horizontalCenter: parent.horizontalCenter
source: root.icon
source: message.icon
}
QQC2.Label {
text: root.text
text: message.text
textFormat: Text.MarkdownText
}
}

View File

@@ -7,14 +7,14 @@ import QtQml 2.15
import org.kde.neochat 1.0
Message {
id: root
id: verificationCanceled
required property int reason
anchors.centerIn: parent
icon: "security-low"
text: {
switch(root.reason) {
switch(verificationCanceled.reason) {
case KeyVerificationSession.NONE:
return i18n("The session verification was canceled for unknown reason.");
case KeyVerificationSession.TIMEOUT:

View File

@@ -6,27 +6,27 @@ import QtQuick 2.15
import QtQuick.Layouts 1.10
Labs.Menu {
id: root
id: editMenu
required property Item field
Labs.MenuItem {
enabled: root.field !== null && root.field.canUndo
enabled: editMenu.field !== null && editMenu.field.canUndo
text: i18nc("text editing menu action", "Undo")
shortcut: StandardKey.Undo
onTriggered: {
root.field.undo()
root.close()
editMenu.field.undo()
editMenu.close()
}
}
Labs.MenuItem {
enabled: root.field !== null && root.field.canRedo
enabled: editMenu.field !== null && editMenu.field.canRedo
text: i18nc("text editing menu action", "Redo")
shortcut: StandardKey.Redo
onTriggered: {
root.field.undo()
root.close()
editMenu.field.undo()
editMenu.close()
}
}
@@ -34,42 +34,42 @@ Labs.Menu {
}
Labs.MenuItem {
enabled: root.field !== null && root.field.selectedText
enabled: editMenu.field !== null && editMenu.field.selectedText
text: i18nc("text editing menu action", "Cut")
shortcut: StandardKey.Cut
onTriggered: {
root.field.cut()
root.close()
editMenu.field.cut()
editMenu.close()
}
}
Labs.MenuItem {
enabled: root.field !== null && root.field.selectedText
enabled: editMenu.field !== null && editMenu.field.selectedText
text: i18nc("text editing menu action", "Copy")
shortcut: StandardKey.Copy
onTriggered: {
root.field.copy()
root.close()
editMenu.field.copy()
editMenu.close()
}
}
Labs.MenuItem {
enabled: root.field !== null && root.field.canPaste
enabled: editMenu.field !== null && editMenu.field.canPaste
text: i18nc("text editing menu action", "Paste")
shortcut: StandardKey.Paste
onTriggered: {
root.field.paste()
root.close()
editMenu.field.paste()
editMenu.close()
}
}
Labs.MenuItem {
enabled: root.field !== null && root.field.selectedText !== ""
enabled: editMenu.field !== null && editMenu.field.selectedText !== ""
text: i18nc("text editing menu action", "Delete")
shortcut: ""
onTriggered: {
root.field.remove(root.field.selectionStart, root.field.selectionEnd)
root.close()
editMenu.field.remove(editMenu.field.selectionStart, editMenu.field.selectionEnd)
editMenu.close()
}
}
@@ -77,12 +77,12 @@ Labs.Menu {
}
Labs.MenuItem {
enabled: root.field !== null
enabled: editMenu.field !== null
text: i18nc("text editing menu action", "Select All")
shortcut: StandardKey.SelectAll
onTriggered: {
root.field.selectAll()
root.close()
editMenu.field.selectAll()
editMenu.close()
}
}
}

View File

@@ -54,16 +54,7 @@ Labs.MenuBar {
}
Labs.MenuItem {
text: i18nc("menu", "Browse Chats…")
onTriggered: {
let dialog = pageStack.pushDialogLayer("qrc:/JoinRoomPage.qml", {connection: Controller.activeConnection}, {title: i18nc("@title", "Explore Rooms")})
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
if (isJoined) {
RoomManager.enterRoom(Controller.activeConnection.room(roomId))
} else {
Controller.joinRoom(roomId)
}
})
}
onTriggered: pushReplaceLayer("qrc:/JoinRoomPage.qml", {connection: Controller.activeConnection})
}
}
EditMenu {

View File

@@ -13,8 +13,7 @@ import org.kde.kirigami 2.14 as Kirigami
* TODO add Android support
*/
Kirigami.Action {
id: root
id: shareAction
icon.name: "emblem-shared-symbolic"
text: i18n("Share")
tooltip: i18n("Share the selected media")
@@ -41,12 +40,12 @@ Kirigami.Action {
const purposeModel = Qt.createQmlObject('import org.kde.purpose 1.0 as Purpose;
Purpose.PurposeAlternativesModel {
pluginType: "Export"
}', root._instantiator);
}', shareAction._instantiator);
purposeModel.inputData = Qt.binding(function() {
return root.inputData;
return shareAction.inputData;
});
_instantiator.model = purposeModel;
root.visible = true;
shareAction.visible = true;
}
delegate: Kirigami.Action {
@@ -56,16 +55,16 @@ Purpose.PurposeAlternativesModel {
onTriggered: {
doBeforeSharing();
applicationWindow().pageStack.pushDialogLayer('qrc:/ShareDialog.qml', {
title: root.tooltip,
title: shareAction.tooltip,
index: index,
model: root._instantiator.model
model: shareAction._instantiator.model
})
}
}
onObjectAdded: (index, object) => {
object.index = index;
root.children.push(object)
shareAction.children.push(object)
}
onObjectRemoved: (index, object) => root.children = Array.from(root.children).filter(obj => obj.pluginId !== object.pluginId)
onObjectRemoved: (index, object) => shareAction.children = Array.from(shareAction.children).filter(obj => obj.pluginId !== object.pluginId)
}
}

View File

@@ -13,7 +13,7 @@ import org.kde.notification 1.0
import org.kde.kirigami 2.14 as Kirigami
Kirigami.Page {
id: root
id: window
leftPadding: 0
rightPadding: 0
@@ -25,7 +25,7 @@ Kirigami.Page {
QQC2.Action {
shortcut: 'Escape'
onTriggered: root.closeDialog()
onTriggered: window.closeDialog()
}
Notification {
@@ -54,15 +54,15 @@ Kirigami.Page {
sharingSuccess.sendEvent();
Clipboard.saveText(jobView.output.url);
}
root.closeDialog()
window.closeDialog()
} else if (state === Purpose.PurposeJobController.Error) {
// Show failure notification
sharingFailed.sendEvent();
root.closeDialog()
window.closeDialog()
} else if (state === Purpose.PurposeJobController.Cancelled) {
// Do nothing
root.closeDialog()
window.closeDialog()
}
}
}

View File

@@ -10,7 +10,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
Kirigami.Page {
id: root
id: banSheet
property NeoChatRoom room
property string userId
@@ -35,14 +35,14 @@ Kirigami.Page {
icon.name: "im-ban-user"
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
onClicked: {
root.room.ban(root.userId, reason.text)
root.closeDialog()
banSheet.room.ban(banSheet.userId, reason.text)
banSheet.closeDialog()
}
}
QQC2.Button {
text: i18nc("@action", "Cancel")
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
onClicked: root.closeDialog()
onClicked: banSheet.closeDialog()
}
}
}

View File

@@ -11,7 +11,7 @@ import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
import org.kde.neochat 1.0
Loader {
id: root
id: loadRoot
required property var author
required property string eventId
@@ -31,7 +31,7 @@ Loader {
currentRoom.chatBoxEditId = eventId;
currentRoom.chatBoxReplyId = "";
}
visible: author.id === Controller.activeConnection.localUserId && (root.eventType === DelegateType.Emote || root.eventType === DelegateType.Message)
visible: author.id === Controller.activeConnection.localUserId && (loadRoot.eventType === DelegateType.Emote || loadRoot.eventType === DelegateType.Message)
},
Kirigami.Action {
text: i18n("Reply")
@@ -50,7 +50,7 @@ Loader {
width: Kirigami.Units.gridUnit * 25
})
page.chosen.connect(function(targetRoomId) {
Controller.activeConnection.room(targetRoomId).postHtmlMessage(root.plainText, root.htmlText ? root.htmlText : root.plainText)
Controller.activeConnection.room(targetRoomId).postHtmlMessage(loadRoot.plainText, loadRoot.htmlText ? loadRoot.htmlText : loadRoot.plainText)
page.closeDialog()
})
}
@@ -68,7 +68,7 @@ Loader {
Kirigami.Action {
text: i18n("Copy")
icon.name: "edit-copy"
onTriggered: Clipboard.saveText(root.selectedText === "" ? root.plainText : root.selectedText)
onTriggered: Clipboard.saveText(loadRoot.selectedText === "" ? loadRoot.plainText : loadRoot.selectedText)
},
Kirigami.Action {
text: i18nc("@action:button 'Report' as in 'Report this event to the administrators'", "Report")
@@ -84,7 +84,7 @@ Loader {
icon.name: "code-context"
onTriggered: {
applicationWindow().pageStack.pushDialogLayer('qrc:/MessageSourceSheet.qml', {
sourceText: root.eventSource
sourceText: loadRoot.source
}, {
title: i18n("Message Source"),
width: Kirigami.Units.gridUnit * 25
@@ -95,7 +95,7 @@ Loader {
text: i18n("Copy Link")
icon.name: "edit-copy"
onTriggered: {
Clipboard.saveText("https://matrix.to/#/" + currentRoom.id + "/" + root.eventId)
Clipboard.saveText("https://matrix.to/#/" + currentRoom.id + "/" + loadRoot.eventId)
}
}
]
@@ -106,7 +106,7 @@ Loader {
QQC2.Menu {
id: menu
Instantiator {
model: root.nestedActions
model: loadRoot.nestedActions
delegate: QQC2.Menu {
id: menuItem
visible: modelData.visible
@@ -131,12 +131,12 @@ Loader {
}
Repeater {
model: root.actions
model: loadRoot.actions
QQC2.MenuItem {
id: menuItem
visible: modelData.visible
action: modelData
onClicked: root.item.close();
onClicked: loadRoot.item.close();
}
}
QQC2.Menu {
@@ -150,7 +150,7 @@ Loader {
Instantiator {
model: WebShortcutModel {
id: webshortcutmodel
selectedText: root.selectedText ? root.selectedText : root.plainText
selectedText: loadRoot.selectedText ? loadRoot.selectedText : loadRoot.plainText
onOpenUrl: RoomManager.visitNonMatrix(url)
}
delegate: QQC2.MenuItem {
@@ -222,7 +222,7 @@ Loader {
text: modelData.text
onClicked: {
modelData.triggered()
root.item.close();
loadRoot.item.close();
}
implicitHeight: visible ? Kirigami.Units.gridUnit * 3 : 0
}
@@ -285,7 +285,7 @@ Loader {
onClicked: {
currentRoom.toggleReaction(eventId, modelData);
root.item.close();
loadRoot.item.close();
}
}
}
@@ -295,7 +295,7 @@ Loader {
}
Repeater {
id: listViewAction
model: root.actions
model: loadRoot.actions
Kirigami.BasicListItem {
icon: modelData.icon.name
@@ -305,14 +305,14 @@ Loader {
text: modelData.text
onClicked: {
modelData.triggered()
root.item.close();
loadRoot.item.close();
}
implicitHeight: visible ? Kirigami.Units.gridUnit * 3 : 0
}
}
Repeater {
model: root.nestedActions
model: loadRoot.nestedActions
Kirigami.BasicListItem {
action: modelData

View File

@@ -10,7 +10,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
Kirigami.Page {
id: root
id: deleteSheet
property NeoChatRoom room
property string eventId
@@ -37,18 +37,18 @@ Kirigami.Page {
icon.name: "delete"
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
onClicked: {
if (root.userId.length > 0) {
root.room.deleteMessagesByUser(root.userId, reason.text)
if (deleteSheet.userId.length > 0) {
deleteSheet.room.deleteMessagesByUser(deleteSheet.userId, reason.text)
} else {
root.room.redactEvent(root.eventId, reason.text);
deleteSheet.room.redactEvent(deleteSheet.eventId, reason.text);
}
root.closeDialog()
deleteSheet.closeDialog()
}
}
QQC2.Button {
text: i18nc("@action", "Cancel")
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
onClicked: root.closeDialog()
onClicked: deleteSheet.closeDialog()
}
}
}

View File

@@ -10,7 +10,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
Kirigami.Page {
id: root
id: reportSheet
property NeoChatRoom room
property string eventId
@@ -35,14 +35,14 @@ Kirigami.Page {
icon.name: "dialog-warning-symbolic"
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
onClicked: {
root.room.reportEvent(eventId, reason.text)
root.closeDialog()
reportSheet.room.reportEvent(eventId, reason.text)
reportSheet.closeDialog()
}
}
QQC2.Button {
text: i18nc("@action", "Cancel")
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
onClicked: root.closeDialog()
onClicked: reportSheet.closeDialog()
}
}
}

View File

@@ -14,6 +14,7 @@ import org.kde.neochat 1.0
Delegates.RoundedItemDelegate {
id: root
required property NeoChatConnection connection
required property string roomId
required property string displayName
required property url avatarUrl
@@ -23,32 +24,16 @@ Delegates.RoundedItemDelegate {
required property bool isJoined
property bool justJoined: false
/**
* @brief Signal emitted when a room delegate is selected.
*
* The signal contains all the delegate's model info so that it can be acted
* upon as required, e.g. joining or entering the room or adding the room as
* the child of a space.
*/
signal roomSelected(string roomId,
string displayName,
url avatarUrl,
string alias,
string topic,
int memberCount,
bool isJoined)
signal roomSelected()
onClicked: {
if (!isJoined) {
Controller.joinRoom(root.roomId)
justJoined = true;
} else {
RoomManager.enterRoom(root.connection.room(root.roomId))
}
root.roomSelected(root.roomId,
root.displayName,
root.avatarUrl,
root.alias,
root.topic,
root.memberCount,
root.isJoined)
root.roomSelected()
}
contentItem: RowLayout {

View File

@@ -20,21 +20,6 @@ Kirigami.ScrollablePage {
property alias keyword: identifierField.text
property string server
/**
* @brief Signal emitted when a room is selected.
*
* The signal contains all the room's info so that it can be acted
* upon as required, e.g. joinng or entering the room or adding the room as
* the child of a space.
*/
signal roomSelected(string roomId,
string displayName,
url avatarUrl,
string alias,
string topic,
int memberCount,
bool isJoined)
title: i18n("Explore Rooms")
Component.onCompleted: identifierField.forceActiveFocus()
@@ -226,10 +211,7 @@ Kirigami.ScrollablePage {
}
delegate: ExplorerDelegate {
connection: root.connection
onRoomSelected: (roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
root.roomSelected(roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined);
root.closeDialog();
}
onRoomSelected: root.closeDialog()
}
footer: RowLayout {

View File

@@ -14,20 +14,12 @@ RowLayout {
property var desiredWidth
property bool collapsed: false
required property NeoChatConnection connection
property Kirigami.Action exploreAction: Kirigami.Action {
text: i18n("Explore rooms")
icon.name: "compass"
onTriggered: {
let dialog = pageStack.pushDialogLayer("qrc:/JoinRoomPage.qml", {connection: Controller.activeConnection}, {title: i18nc("@title", "Explore Rooms")})
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
if (isJoined) {
RoomManager.enterRoom(Controller.activeConnection.room(roomId))
} else {
Controller.joinRoom(roomId)
}
})
pageStack.pushDialogLayer("qrc:/JoinRoomPage.qml", {connection: Controller.activeConnection}, {title: i18nc("@title", "Explore Rooms")})
}
}
property Kirigami.Action chatAction: Kirigami.Action {
@@ -39,7 +31,7 @@ RowLayout {
text: i18n("Create a Room")
icon.name: "system-users"
onTriggered: {
pageStack.pushDialogLayer("qrc:/CreateRoomDialog.qml", {connection: root.connection}, {title: i18nc("@title", "Create a Room")})
pageStack.pushDialogLayer("qrc:/CreateRoomDialog.qml", {}, {title: i18nc("@title", "Create a Room")})
}
shortcut: StandardKey.New
}
@@ -47,7 +39,7 @@ RowLayout {
text: i18n("Create a Space")
icon.name: "list-add"
onTriggered: {
pageStack.pushDialogLayer("qrc:/CreateSpaceDialog.qml", {connection: root.connection}, {title: i18nc("@title", "Create a Space")})
pageStack.pushDialogLayer("qrc:/CreateSpaceDialog.qml", {}, {title: i18nc("@title", "Create a Space")})
}
}

View File

@@ -89,14 +89,13 @@ Kirigami.Page {
Layout.fillWidth: true
desiredWidth: root.width - Kirigami.Units.largeSpacing
collapsed: root.collapsed
connection: root.connection
}
padding: 0
RowLayout {
anchors.fill: parent
spacing: 0
spacing: 1
NeoChat.SpaceDrawer {
id: spaceDrawer
@@ -104,11 +103,6 @@ Kirigami.Page {
Layout.fillHeight: true
}
Kirigami.Separator {
Layout.fillHeight: true
Layout.preferredWidth: 1
}
QQC2.ScrollView {
id: scrollView
Layout.fillWidth: true
@@ -159,21 +153,10 @@ Kirigami.Page {
helpfulAction: Kirigami.Action {
icon.name: sortFilterRoomListModel.filterText.length > 0 ? "search" : "list-add"
text: sortFilterRoomListModel.filterText.length > 0 ? i18n("Search in room directory") : i18n("Explore rooms")
onTriggered: {
let dialog = pageStack.layers.push("qrc:/JoinRoomPage.qml", {
connection: Controller.activeConnection,
keyword: sortFilterRoomListModel.filterText
}, {
title: i18nc("@title", "Explore Rooms")
})
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
if (isJoined) {
RoomManager.enterRoom(Controller.activeConnection.room(roomId))
} else {
Controller.joinRoom(roomId)
}
})
}
onTriggered: pageStack.layers.push("qrc:/JoinRoomPage.qml", {
connection: Controller.activeConnection,
keyword: sortFilterRoomListModel.filterText
})
}
}

View File

@@ -93,7 +93,7 @@ Delegates.RoundedItemDelegate {
enabled: false
implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium
visible: currentRoom.pushNotificationState === PushNotificationState.Mute && !configButton.visible && !hasNotifications
visible: currentRoom.pushNotificationState === PushNotificationState.Mute && !hasNotifications
Accessible.name: i18n("Muted room")
Layout.rightMargin: Kirigami.Units.smallSpacing
}
@@ -122,16 +122,6 @@ Delegates.RoundedItemDelegate {
text: notificationCountLabel.text
}
}
QQC2.Button {
id: configButton
visible: root.hovered && !Kirigami.Settings.isMobile && !Config.compactRoomList
text: i18n("Configure room")
display: QQC2.Button.IconOnly
icon.name: "configure"
onClicked: createRoomListContextMenu()
}
}
function createRoomListContextMenu() {
@@ -139,17 +129,6 @@ Delegates.RoundedItemDelegate {
const menu = component.createObject(root, {
room: root.currentRoom,
});
if (!Kirigami.Settings.isMobile && !Config.compactRoomList) {
configButton.visible = true;
configButton.down = true;
}
menu.closed.connect(function() {
configButton.down = undefined;
configButton.visible = Qt.binding(() => {
return root.hovered && !Kirigami.Settings.isMobile
&& !Config.compactRoomList;
});
})
menu.open()
}
}

View File

@@ -41,11 +41,6 @@ QQC2.Control {
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
contentWidth: -1 // disable horizontal scroll
background: Rectangle {
color: Kirigami.Theme.backgroundColor
Kirigami.Theme.colorSet: Kirigami.Theme.View
}
ColumnLayout {
id: column
width: scrollView.width

View File

@@ -11,7 +11,7 @@ import org.kde.kirigamiaddons.delegates 1.0 as Delegates
import org.kde.neochat 1.0
QQC2.ToolBar {
id: root
id: userInfo
padding: 0
@@ -33,7 +33,7 @@ QQC2.ToolBar {
id: addButton
width: parent.width
highlighted: focus || (addAccount.highlighted || addAccount.ListView.isCurrentItem) && !addAccount.pressed
Component.onCompleted: root.addAccount = this
Component.onCompleted: userInfo.addAccount = this
icon {
name: "list-add"
width: Kirigami.Units.iconSizes.smallMedium

View File

@@ -97,8 +97,6 @@ Kirigami.Page {
}
background: Rectangle {
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
color: Config.compactLayout ? Kirigami.Theme.backgroundColor : "transparent"
}

View File

@@ -10,24 +10,23 @@ import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
Kirigami.ApplicationWindow {
id: root
id: window
required property NeoChatRoom currentRoom
minimumWidth: Kirigami.Units.gridUnit * 10
minimumHeight: Kirigami.Units.gridUnit * 15
Shortcut {
sequence: StandardKey.Cancel
onActivated: root.close()
onActivated: window.close()
}
pageStack.initialPage: RoomPage {
visible: true
currentRoom: root.currentRoom
currentRoom: window.currentRoom
disableCancelShortcut: true
}
onCurrentRoomChanged: if (!currentRoom) {
root.close()
window.close()
}
property Item hoverLinkIndicator: QQC2.Control {

View File

@@ -10,7 +10,7 @@ import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
Kirigami.ScrollablePage {
id: root
id: searchPage
property NeoChatRoom currentRoom
@@ -22,7 +22,7 @@ Kirigami.ScrollablePage {
id: searchModel
connection: Controller.activeConnection
searchText: searchField.text
room: root.currentRoom
room: searchPage.currentRoom
}
header: RowLayout {

View File

@@ -9,8 +9,8 @@ import Qt.labs.platform 1.1
import QtQuick.Window 2.15
import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.components 1.0 as KirigamiComponents
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
import org.kde.neochat 1.0
FormCard.FormCardPage {
@@ -19,10 +19,8 @@ FormCard.FormCardPage {
title: i18n("Edit Account")
property NeoChatConnection connection
KirigamiComponents.AvatarButton {
id: avatar
property OpenFileDialog fileDialog: null
QQC2.RoundButton {
property var fileDialog: null;
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.topMargin: Kirigami.Units.largeSpacing
@@ -33,20 +31,26 @@ FormCard.FormCardPage {
padding: 0
source: root.connection && root.connection.localUser.avatarMediaId ? ("image://mxc/" + root.connection.localUser.avatarMediaId) : ""
name: root.connection.localUser.displayName
contentItem: KirigamiComponents.Avatar {
id: avatar
source: root.connection && root.connection.localUser.avatarMediaId ? ("image://mxc/" + root.connection.localUser.avatarMediaId) : ""
name: root.connection.localUser.displayName
}
onClicked: {
if (fileDialog) {
if (fileDialog != null) {
return;
}
fileDialog = openFileDialog.createObject(this);
fileDialog.chosen.connect((receivedSource) => {
fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.Overlay)
fileDialog.chosen.connect(function(receivedSource) {
if (!receivedSource) {
return;
}
source = receivedSource;
avatar.source = receivedSource;
});
fileDialog.onRejected.connect(function() {
mouseArea.fileDialog = null;
});
fileDialog.open();
}
@@ -90,9 +94,6 @@ FormCard.FormCardPage {
OpenFileDialog {
folder: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
parentWindow: root.Window.window
onAccepted: destroy()
onRejected: destroy()
}
}
}

View File

@@ -12,7 +12,7 @@ import org.kde.kirigamiaddons.formcard 1.0 as FormCard
import org.kde.neochat 1.0
FormCard.AbstractFormDelegate {
id: root
id: deviceDelegate
required property string id
required property string timestamp
@@ -21,7 +21,7 @@ FormCard.AbstractFormDelegate {
property bool editDeviceName: false
property bool showVerifyButton
onClicked: root.editDeviceName = true
onClicked: deviceDelegate.editDeviceName = true
contentItem: RowLayout {
spacing: Kirigami.Units.largeSpacing
@@ -35,11 +35,11 @@ FormCard.AbstractFormDelegate {
id: deviceLabel
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
visible: !root.editDeviceName
visible: !deviceDelegate.editDeviceName
QQC2.Label {
Layout.fillWidth: true
text: root.displayName
text: deviceDelegate.displayName
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 2
@@ -47,7 +47,7 @@ FormCard.AbstractFormDelegate {
QQC2.Label {
Layout.fillWidth: true
text: i18nc("@label", "%1, Last activity: %2", root.id, root.timestamp)
text: i18nc("@label", "%1, Last activity: %2", deviceDelegate.id, deviceDelegate.timestamp)
color: Kirigami.Theme.disabledTextColor
font: Kirigami.Theme.smallFont
elide: Text.ElideRight
@@ -59,29 +59,29 @@ FormCard.AbstractFormDelegate {
Accessible.description: i18n("New device name")
Layout.fillWidth: true
Layout.preferredHeight: deviceLabel.implicitHeight
visible: root.editDeviceName
visible: deviceDelegate.editDeviceName
text: root.displayName
text: deviceDelegate.displayName
rightActions: [
Kirigami.Action {
text: i18n("Cancel editing display name")
icon.name: "edit-delete-remove"
onTriggered: {
root.editDeviceName = false
deviceDelegate.editDeviceName = false
}
},
Kirigami.Action {
text: i18n("Confirm new display name")
icon.name: "checkmark"
visible: nameField.text !== root.displayName
visible: nameField.text !== deviceDelegate.displayName
onTriggered: {
devicesModel.setName(root.id, nameField.text)
devicesModel.setName(deviceDelegate.id, nameField.text)
}
}
]
onAccepted: devicesModel.setName(root.id, nameField.text)
onAccepted: devicesModel.setName(deviceDelegate.id, nameField.text)
}
QQC2.ToolButton {
display: QQC2.AbstractButton.IconOnly
@@ -89,7 +89,7 @@ FormCard.AbstractFormDelegate {
id: editDeviceAction
text: i18n("Edit device name")
icon.name: "document-edit"
onTriggered: root.editDeviceName = true
onTriggered: deviceDelegate.editDeviceName = true
}
QQC2.ToolTip {
text: editDeviceAction.text
@@ -98,13 +98,13 @@ FormCard.AbstractFormDelegate {
}
QQC2.ToolButton {
display: QQC2.AbstractButton.IconOnly
visible: root.showVerifyButton
visible: deviceDelegate.showVerifyButton
action: Kirigami.Action {
id: verifyDeviceAction
text: i18n("Verify device")
icon.name: "security-low-symbolic"
onTriggered: {
devicesModel.connection.startKeyVerificationSession(devicesModel.connection.localUserId, root.id)
devicesModel.connection.startKeyVerificationSession(devicesModel.connection.localUserId, deviceDelegate.id)
}
}
QQC2.ToolTip {
@@ -119,7 +119,7 @@ FormCard.AbstractFormDelegate {
text: i18n("Logout device")
icon.name: "edit-delete-remove"
onTriggered: {
passwordSheet.deviceId = root.id
passwordSheet.deviceId = deviceDelegate.id
passwordSheet.open()
}
}

View File

@@ -9,7 +9,7 @@ import QtQuick.Layouts 1.15
import org.kde.neochat 1.0
KirigamiSettings.CategorizedSettings {
id: root
id: settingsPage
required property NeoChatConnection connection
@@ -66,7 +66,7 @@ KirigamiSettings.CategorizedSettings {
page: Qt.resolvedUrl("DevicesPage.qml")
initialProperties: {
return {
connection: root.connection
connection: settingsPage.connection
}
}
},

View File

@@ -9,7 +9,7 @@ import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami
QQC2.RadioButton {
id: root
id: delegate
implicitWidth: contentItem.implicitWidth
implicitHeight: contentItem.implicitHeight
@@ -20,7 +20,7 @@ QQC2.RadioButton {
contentItem: ColumnLayout {
Kirigami.ShadowedRectangle {
implicitWidth: implicitHeight * 1.6
implicitHeight: root.thin ? Kirigami.Units.gridUnit * 5 : Kirigami.Units.gridUnit * 6
implicitHeight: delegate.thin ? Kirigami.Units.gridUnit * 5 : Kirigami.Units.gridUnit * 6
radius: Kirigami.Units.smallSpacing
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.View
@@ -31,9 +31,9 @@ QQC2.RadioButton {
shadow.color: Qt.rgba(0, 0, 0, 0.3)
color: {
if (root.checked) {
if (delegate.checked) {
return Kirigami.Theme.highlightColor;
} else if (root.hovered) {
} else if (delegate.hovered) {
// Match appearance of hovered list items
return Qt.rgba(Kirigami.Theme.highlightColor.r,
Kirigami.Theme.highlightColor.g,
@@ -54,7 +54,7 @@ QQC2.RadioButton {
QQC2.Label {
id: label
Layout.fillWidth: true
text: root.text
text: delegate.text
horizontalAlignment: Text.AlignHCenter
}
}

View File

@@ -190,8 +190,6 @@ Kirigami.ApplicationWindow {
RoomList.Page {
id: roomList
connection: Controller.activeConnection
Shortcut {
sequences: ["Ctrl+PgUp", "Ctrl+Backtab", "Alt+Up"]
onActivated: {
@@ -241,7 +239,9 @@ Kirigami.ApplicationWindow {
if (AccountRegistry.accountCount === 0) {
pageStack.replace("qrc:/WelcomePage.qml", {});
} else if (!roomListLoaded) {
pageStack.replace(roomListComponent);
pageStack.replace(roomListComponent, {
connection: Controller.activeConnection
});
roomListLoaded = true;
roomListPage = pageStack.currentItem
RoomManager.loadInitialRoom();
@@ -320,16 +320,12 @@ Kirigami.ApplicationWindow {
Component {
id: createRoomDialog
CreateRoomDialog {
connection: Controller.activeConnection
}
CreateRoomDialog {}
}
Component {
id: createSpaceDialog
CreateSpaceDialog {
connection: Controller.activeConnection
}
CreateSpaceDialog {}
}
Component {