diff options
-rw-r--r-- | resources/qml/RoomList.qml | 19 | ||||
-rw-r--r-- | src/MainWindow.cpp | 1 | ||||
-rw-r--r-- | src/SideBarActions.cpp | 120 | ||||
-rw-r--r-- | src/SideBarActions.h | 54 | ||||
-rw-r--r-- | src/Splitter.cpp | 166 | ||||
-rw-r--r-- | src/Splitter.h | 49 | ||||
-rw-r--r-- | src/UserInfoWidget.cpp | 219 | ||||
-rw-r--r-- | src/UserInfoWidget.h | 68 | ||||
-rw-r--r-- | src/ui/NhekoGlobalObject.cpp | 27 | ||||
-rw-r--r-- | src/ui/NhekoGlobalObject.h | 4 |
10 files changed, 50 insertions, 677 deletions
diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index c5e07032..3109b75c 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -477,6 +477,7 @@ Page { image: ":/icons/icons/ui/power-button-off.png" ToolTip.visible: hovered ToolTip.text: qsTr("Logout") + onClicked: Nheko.openLogoutDialog() } } @@ -523,6 +524,23 @@ Page { ToolTip.visible: hovered ToolTip.text: qsTr("Start a new chat") Layout.margins: Nheko.paddingMedium + + onClicked: roomJoinCreateMenu.open(parent) + + Platform.Menu { + id: roomJoinCreateMenu + + Platform.MenuItem { + text: qsTr("Join a room") + onTriggered: Nheko.openJoinRoomDialog() + } + + Platform.MenuItem { + text: qsTr("Create a new room") + onTriggered: Nheko.openCreateRoomDialog() + } + + } } ImageButton { @@ -545,6 +563,7 @@ Page { ToolTip.visible: hovered ToolTip.text: qsTr("User settings") Layout.margins: Nheko.paddingMedium + onClicked: Nheko.showUserSettingsPage() } } diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 057ee4af..ed337ca4 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -22,7 +22,6 @@ #include "MainWindow.h" #include "MatrixClient.h" #include "RegisterPage.h" -#include "Splitter.h" #include "TrayIcon.h" #include "UserSettingsPage.h" #include "Utils.h" diff --git a/src/SideBarActions.cpp b/src/SideBarActions.cpp deleted file mode 100644 index 0b7756f0..00000000 --- a/src/SideBarActions.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include <QIcon> -#include <QPainter> -#include <QResizeEvent> -#include <QStyle> -#include <QStyleOption> - -#include <mtx/requests.hpp> - -#include "Config.h" -#include "MainWindow.h" -#include "SideBarActions.h" -#include "Splitter.h" -#include "ui/FlatButton.h" -#include "ui/Menu.h" - -SideBarActions::SideBarActions(QWidget *parent) - : QWidget{parent} -{ - QFont f; - f.setPointSizeF(f.pointSizeF()); - - const int fontHeight = QFontMetrics(f).height(); - const int contentHeight = fontHeight * 2.5; - - setFixedHeight(contentHeight); - - layout_ = new QHBoxLayout(this); - layout_->setMargin(0); - - QIcon settingsIcon; - settingsIcon.addFile(":/icons/icons/ui/settings.png"); - - QIcon createRoomIcon; - createRoomIcon.addFile(":/icons/icons/ui/add-square-button.png"); - - QIcon joinRoomIcon; - joinRoomIcon.addFile(":/icons/icons/ui/speech-bubbles-comment-option.png"); - - settingsBtn_ = new FlatButton(this); - settingsBtn_->setToolTip(tr("User settings")); - settingsBtn_->setIcon(settingsIcon); - settingsBtn_->setCornerRadius(conf::sidebarActions::iconSize / 2); - settingsBtn_->setIconSize( - QSize(conf::sidebarActions::iconSize, conf::sidebarActions::iconSize)); - - addMenu_ = new Menu(this); - createRoomAction_ = new QAction(tr("Create new room"), this); - joinRoomAction_ = new QAction(tr("Join a room"), this); - - connect(joinRoomAction_, &QAction::triggered, this, [this]() { - MainWindow::instance()->openJoinRoomDialog( - [this](const QString &room_id) { emit joinRoom(room_id); }); - }); - - connect(createRoomAction_, &QAction::triggered, this, [this]() { - MainWindow::instance()->openCreateRoomDialog( - [this](const mtx::requests::CreateRoom &req) { emit createRoom(req); }); - }); - - addMenu_->addAction(createRoomAction_); - addMenu_->addAction(joinRoomAction_); - - createRoomBtn_ = new FlatButton(this); - createRoomBtn_->setToolTip(tr("Start a new chat")); - createRoomBtn_->setIcon(createRoomIcon); - createRoomBtn_->setCornerRadius(conf::sidebarActions::iconSize / 2); - createRoomBtn_->setIconSize( - QSize(conf::sidebarActions::iconSize, conf::sidebarActions::iconSize)); - - connect(createRoomBtn_, &QPushButton::clicked, this, [this]() { - auto pos = mapToGlobal(createRoomBtn_->pos()); - auto padding = conf::sidebarActions::iconSize / 2; - - addMenu_->popup( - QPoint(pos.x() + padding, pos.y() - padding - addMenu_->sizeHint().height())); - }); - - roomDirectory_ = new FlatButton(this); - roomDirectory_->setToolTip(tr("Room directory")); - roomDirectory_->setEnabled(false); - roomDirectory_->setIcon(joinRoomIcon); - roomDirectory_->setCornerRadius(conf::sidebarActions::iconSize / 2); - roomDirectory_->setIconSize( - QSize(conf::sidebarActions::iconSize, conf::sidebarActions::iconSize)); - - layout_->addWidget(createRoomBtn_); - layout_->addWidget(roomDirectory_); - layout_->addWidget(settingsBtn_); - - connect(settingsBtn_, &QPushButton::clicked, this, &SideBarActions::showSettings); -} - -void -SideBarActions::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - - const auto sidebarSizes = splitter::calculateSidebarSizes(QFont{}); - - if (width() <= sidebarSizes.small) { - roomDirectory_->hide(); - createRoomBtn_->hide(); - } else { - roomDirectory_->show(); - createRoomBtn_->show(); - } -} - -void -SideBarActions::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} diff --git a/src/SideBarActions.h b/src/SideBarActions.h deleted file mode 100644 index 566aa76b..00000000 --- a/src/SideBarActions.h +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <QAction> -#include <QHBoxLayout> -#include <QWidget> - -namespace mtx { -namespace requests { -struct CreateRoom; -} -} - -class Menu; -class FlatButton; -class QResizeEvent; - -class SideBarActions : public QWidget -{ - Q_OBJECT - - Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor) - -public: - SideBarActions(QWidget *parent = nullptr); - - QColor borderColor() const { return borderColor_; } - void setBorderColor(QColor &color) { borderColor_ = color; } - -signals: - void showSettings(); - void joinRoom(const QString &room); - void createRoom(const mtx::requests::CreateRoom &request); - -protected: - void resizeEvent(QResizeEvent *event) override; - void paintEvent(QPaintEvent *event) override; - -private: - QHBoxLayout *layout_; - - Menu *addMenu_; - QAction *createRoomAction_; - QAction *joinRoomAction_; - - FlatButton *settingsBtn_; - FlatButton *createRoomBtn_; - FlatButton *roomDirectory_; - - QColor borderColor_; -}; diff --git a/src/Splitter.cpp b/src/Splitter.cpp deleted file mode 100644 index 15e3f5c5..00000000 --- a/src/Splitter.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr> -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include <QSettings> - -#include "Logging.h" -#include "Splitter.h" - -constexpr auto MaxWidth = (1 << 24) - 1; - -Splitter::Splitter(QWidget *parent) - : QSplitter(parent) - , sz_{splitter::calculateSidebarSizes(QFont{})} -{ - connect(this, &QSplitter::splitterMoved, this, &Splitter::onSplitterMoved); - setChildrenCollapsible(false); -} - -void -Splitter::restoreSizes(int fallback) -{ - QSettings settings; - int savedWidth = settings.value("sidebar/width").toInt(); - - auto left = widget(0); - if (savedWidth <= 0) { - hideSidebar(); - return; - } else if (savedWidth <= sz_.small) { - if (left) { - left->setMinimumWidth(sz_.small); - left->setMaximumWidth(sz_.small); - return; - } - } else if (savedWidth < sz_.normal) { - savedWidth = sz_.normal; - } - - left->setMinimumWidth(sz_.normal); - left->setMaximumWidth(2 * sz_.normal); - setSizes({savedWidth, fallback - savedWidth}); - - setStretchFactor(0, 0); - setStretchFactor(1, 1); -} - -Splitter::~Splitter() -{ - auto left = widget(0); - - if (left) { - QSettings settings; - settings.setValue("sidebar/width", left->width()); - } -} - -void -Splitter::onSplitterMoved(int pos, int index) -{ - Q_UNUSED(pos); - Q_UNUSED(index); - - auto s = sizes(); - - if (s.count() < 2) { - nhlog::ui()->warn("Splitter needs at least two children"); - return; - } - - if (s[0] == sz_.normal) { - rightMoveCount_ += 1; - - if (rightMoveCount_ > moveEventLimit_) { - auto left = widget(0); - auto cursorPosition = left->mapFromGlobal(QCursor::pos()); - - // if we are coming from the right, the cursor should - // end up on the first widget. - if (left->rect().contains(cursorPosition)) { - left->setMinimumWidth(sz_.small); - left->setMaximumWidth(sz_.small); - - rightMoveCount_ = 0; - } - } - } else if (s[0] == sz_.small) { - leftMoveCount_ += 1; - - if (leftMoveCount_ > moveEventLimit_) { - auto left = widget(0); - auto right = widget(1); - auto cursorPosition = right->mapFromGlobal(QCursor::pos()); - - // We move the start a little further so the transition isn't so abrupt. - auto extended = right->rect(); - extended.translate(100, 0); - - // if we are coming from the left, the cursor should - // end up on the second widget. - if (extended.contains(cursorPosition) && - right->size().width() >= sz_.collapsePoint + sz_.normal) { - left->setMinimumWidth(sz_.normal); - left->setMaximumWidth(2 * sz_.normal); - - leftMoveCount_ = 0; - } - } - } -} - -void -Splitter::hideSidebar() -{ - auto left = widget(0); - if (left) - left->hide(); -} - -void -Splitter::showChatView() -{ - auto left = widget(0); - auto right = widget(1); - - if (right->isHidden()) { - left->hide(); - right->show(); - - // Restore previous size. - if (left->minimumWidth() == sz_.small) { - left->setMinimumWidth(sz_.small); - left->setMaximumWidth(sz_.small); - } else { - left->setMinimumWidth(sz_.normal); - left->setMaximumWidth(2 * sz_.normal); - } - } -} - -void -Splitter::showFullRoomList() -{ - auto left = widget(0); - auto right = widget(1); - - right->hide(); - - left->show(); - left->setMaximumWidth(MaxWidth); -} - -splitter::SideBarSizes -splitter::calculateSidebarSizes(const QFont &f) -{ - const auto height = static_cast<double>(QFontMetrics{f}.lineSpacing()); - - SideBarSizes sz; - sz.small = std::ceil(3.8 * height); - sz.normal = std::ceil(16 * height); - sz.groups = std::ceil(3 * height); - sz.collapsePoint = 2 * sz.normal; - - return sz; -} diff --git a/src/Splitter.h b/src/Splitter.h deleted file mode 100644 index 94622f89..00000000 --- a/src/Splitter.h +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr> -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <QSplitter> - -namespace splitter { -struct SideBarSizes -{ - int small; - int normal; - int groups; - int collapsePoint; -}; - -SideBarSizes -calculateSidebarSizes(const QFont &f); -} - -class Splitter : public QSplitter -{ - Q_OBJECT -public: - explicit Splitter(QWidget *parent = nullptr); - ~Splitter() override; - - void restoreSizes(int fallback); - -public slots: - void hideSidebar(); - void showFullRoomList(); - void showChatView(); - -signals: - void hiddenSidebar(); - -private: - void onSplitterMoved(int pos, int index); - - int moveEventLimit_ = 50; - - int leftMoveCount_ = 0; - int rightMoveCount_ = 0; - - splitter::SideBarSizes sz_; -}; diff --git a/src/UserInfoWidget.cpp b/src/UserInfoWidget.cpp deleted file mode 100644 index 3d526b8b..00000000 --- a/src/UserInfoWidget.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr> -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include <QInputDialog> -#include <QLabel> -#include <QMenu> -#include <QPainter> -#include <QStyle> -#include <QStyleOption> -#include <QTimer> - -#include <iostream> - -#include "ChatPage.h" -#include "Config.h" -#include "MainWindow.h" -#include "Splitter.h" -#include "UserInfoWidget.h" -#include "UserSettingsPage.h" -#include "ui/Avatar.h" -#include "ui/FlatButton.h" -#include "ui/OverlayModal.h" - -UserInfoWidget::UserInfoWidget(QWidget *parent) - : QWidget(parent) - , display_name_("User") - , user_id_("@user:homeserver.org") -{ - QFont f; - f.setPointSizeF(f.pointSizeF()); - - const int fontHeight = QFontMetrics(f).height(); - const int widgetMargin = fontHeight / 3; - const int contentHeight = fontHeight * 3; - - logoutButtonSize_ = std::min(fontHeight, 20); - - setFixedHeight(contentHeight + widgetMargin); - - topLayout_ = new QHBoxLayout(this); - topLayout_->setSpacing(0); - topLayout_->setMargin(widgetMargin); - - avatarLayout_ = new QHBoxLayout(); - textLayout_ = new QVBoxLayout(); - textLayout_->setSpacing(widgetMargin / 2); - textLayout_->setContentsMargins(widgetMargin * 2, widgetMargin, widgetMargin, widgetMargin); - - userAvatar_ = new Avatar(this, fontHeight * 2.5); - userAvatar_->setObjectName("userAvatar"); - userAvatar_->setLetter(QChar('?')); - - QFont nameFont; - nameFont.setPointSizeF(nameFont.pointSizeF() * 1.1); - nameFont.setWeight(QFont::Medium); - - displayNameLabel_ = new QLabel(this); - displayNameLabel_->setFont(nameFont); - displayNameLabel_->setObjectName("displayNameLabel"); - displayNameLabel_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop); - - userIdLabel_ = new QLabel(this); - userIdLabel_->setFont(f); - userIdLabel_->setObjectName("userIdLabel"); - userIdLabel_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter); - - avatarLayout_->addWidget(userAvatar_); - textLayout_->addWidget(displayNameLabel_, 0, Qt::AlignBottom); - textLayout_->addWidget(userIdLabel_, 0, Qt::AlignTop); - - topLayout_->addLayout(avatarLayout_); - topLayout_->addLayout(textLayout_); - topLayout_->addStretch(1); - - buttonLayout_ = new QHBoxLayout(); - buttonLayout_->setSpacing(0); - buttonLayout_->setMargin(0); - - logoutButton_ = new FlatButton(this); - logoutButton_->setToolTip(tr("Logout")); - logoutButton_->setCornerRadius(logoutButtonSize_ / 2); - - QIcon icon; - icon.addFile(":/icons/icons/ui/power-button-off.png"); - - logoutButton_->setIcon(icon); - logoutButton_->setIconSize(QSize(logoutButtonSize_, logoutButtonSize_)); - - buttonLayout_->addWidget(logoutButton_); - - topLayout_->addLayout(buttonLayout_); - - // Show the confirmation dialog. - connect(logoutButton_, &QPushButton::clicked, this, []() { - MainWindow::instance()->openLogoutDialog(); - }); - - menu = new QMenu(this); - - auto setStatusAction = menu->addAction(tr("Set custom status message")); - connect(setStatusAction, &QAction::triggered, this, [this]() { - bool ok = false; - QString text = QInputDialog::getText(this, - tr("Custom status message"), - tr("Status:"), - QLineEdit::Normal, - ChatPage::instance()->status(), - &ok); - if (ok) - ChatPage::instance()->setStatus(text); - }); - - auto userProfileAction = menu->addAction(tr("User Profile Settings")); - connect( - userProfileAction, &QAction::triggered, this, [this]() { emit openGlobalUserProfile(); }); - -#if 0 // disable presence menu until issues in synapse are resolved - auto setAutoPresence = menu->addAction(tr("Set presence automatically")); - connect(setAutoPresence, &QAction::triggered, this, []() { - ChatPage::instance()->userSettings()->setPresence( - UserSettings::Presence::AutomaticPresence); - ChatPage::instance()->setStatus(ChatPage::instance()->status()); - }); - auto setOnline = menu->addAction(tr("Online")); - connect(setOnline, &QAction::triggered, this, []() { - ChatPage::instance()->userSettings()->setPresence(UserSettings::Presence::Online); - ChatPage::instance()->setStatus(ChatPage::instance()->status()); - }); - auto setUnavailable = menu->addAction(tr("Unavailable")); - connect(setUnavailable, &QAction::triggered, this, []() { - ChatPage::instance()->userSettings()->setPresence( - UserSettings::Presence::Unavailable); - ChatPage::instance()->setStatus(ChatPage::instance()->status()); - }); - auto setOffline = menu->addAction(tr("Offline")); - connect(setOffline, &QAction::triggered, this, []() { - ChatPage::instance()->userSettings()->setPresence(UserSettings::Presence::Offline); - ChatPage::instance()->setStatus(ChatPage::instance()->status()); - }); -#endif -} - -void -UserInfoWidget::contextMenuEvent(QContextMenuEvent *event) -{ - menu->popup(event->globalPos()); -} - -void -UserInfoWidget::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - - const auto sz = splitter::calculateSidebarSizes(QFont{}); - - if (width() <= sz.small) { - topLayout_->setContentsMargins(0, 0, logoutButtonSize_, 0); - - userAvatar_->hide(); - displayNameLabel_->hide(); - userIdLabel_->hide(); - } else { - topLayout_->setMargin(5); - userAvatar_->show(); - displayNameLabel_->show(); - userIdLabel_->show(); - } - - QWidget::resizeEvent(event); -} - -void -UserInfoWidget::reset() -{ - displayNameLabel_->setText(""); - userIdLabel_->setText(""); - userAvatar_->setLetter(QChar('?')); -} - -void -UserInfoWidget::setDisplayName(const QString &name) -{ - if (name.isEmpty()) - display_name_ = user_id_.split(':')[0].split('@')[1]; - else - display_name_ = name; - - displayNameLabel_->setText(display_name_); - userAvatar_->setLetter(QChar(display_name_[0])); - update(); -} - -void -UserInfoWidget::setUserId(const QString &userid) -{ - user_id_ = userid; - userIdLabel_->setText(userid); - update(); -} - -void -UserInfoWidget::setAvatar(const QString &url) -{ - userAvatar_->setImage(url); - update(); -} - -void -UserInfoWidget::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} diff --git a/src/UserInfoWidget.h b/src/UserInfoWidget.h deleted file mode 100644 index 5aec1cda..00000000 --- a/src/UserInfoWidget.h +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr> -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <QWidget> - -class Avatar; -class FlatButton; -class OverlayModal; - -class QLabel; -class QHBoxLayout; -class QVBoxLayout; -class QMenu; - -class UserInfoWidget : public QWidget -{ - Q_OBJECT - - Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor) - -public: - UserInfoWidget(QWidget *parent = nullptr); - - void setDisplayName(const QString &name); - void setUserId(const QString &userid); - void setAvatar(const QString &url); - - void reset(); - - QColor borderColor() const { return borderColor_; } - void setBorderColor(QColor &color) { borderColor_ = color; } - -protected: - void resizeEvent(QResizeEvent *event) override; - void paintEvent(QPaintEvent *event) override; - void contextMenuEvent(QContextMenuEvent *) override; - -signals: - void openGlobalUserProfile(); - -private: - Avatar *userAvatar_; - - QHBoxLayout *topLayout_; - QHBoxLayout *avatarLayout_; - QVBoxLayout *textLayout_; - QHBoxLayout *buttonLayout_; - - FlatButton *logoutButton_; - - QLabel *displayNameLabel_; - QLabel *userIdLabel_; - - QString display_name_; - QString user_id_; - - QImage avatar_image_; - - int logoutButtonSize_; - - QColor borderColor_; - - QMenu *menu = nullptr; -}; diff --git a/src/ui/NhekoGlobalObject.cpp b/src/ui/NhekoGlobalObject.cpp index fd572b4b..fea10839 100644 --- a/src/ui/NhekoGlobalObject.cpp +++ b/src/ui/NhekoGlobalObject.cpp @@ -10,6 +10,7 @@ #include "Cache_p.h" #include "ChatPage.h" #include "Logging.h" +#include "MainWindow.h" #include "UserSettingsPage.h" #include "Utils.h" @@ -113,3 +114,29 @@ Nheko::currentUser() const return currentUser_.get(); } + +void +Nheko::showUserSettingsPage() const +{ + ChatPage::instance()->showUserSettingsPage(); +} + +void +Nheko::openLogoutDialog() const +{ + MainWindow::instance()->openLogoutDialog(); +} + +void +Nheko::openCreateRoomDialog() const +{ + MainWindow::instance()->openCreateRoomDialog( + [](const mtx::requests::CreateRoom &req) { ChatPage::instance()->createRoom(req); }); +} + +void +Nheko::openJoinRoomDialog() const +{ + MainWindow::instance()->openJoinRoomDialog( + [](const QString &room_id) { ChatPage::instance()->joinRoom(room_id); }); +} diff --git a/src/ui/NhekoGlobalObject.h b/src/ui/NhekoGlobalObject.h index 593514fa..14135fd1 100644 --- a/src/ui/NhekoGlobalObject.h +++ b/src/ui/NhekoGlobalObject.h @@ -40,6 +40,10 @@ public: Q_INVOKABLE void openLink(QString link) const; Q_INVOKABLE void setStatusMessage(QString msg) const; + Q_INVOKABLE void showUserSettingsPage() const; + Q_INVOKABLE void openLogoutDialog() const; + Q_INVOKABLE void openCreateRoomDialog() const; + Q_INVOKABLE void openJoinRoomDialog() const; public slots: void updateUserProfile(); |