Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 80 additions & 1 deletion src/server/src/qml/launcher-window.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#include "launcher-window.hpp"
#include "actions/extension/extension-actions.hpp"
#include "actions/root-search/root-search-actions.hpp"
#include "clipboard-actions.hpp"
#include "extension/extension-command.hpp"
#include "launcher-window-platform.hpp"
#include "hud-bridge.hpp"
#include "keybind-bridge.hpp"
Expand All @@ -17,7 +21,10 @@
#include "navigation-controller.hpp"
#include "overlay-controller/overlay-controller.hpp"
#include "extensions/vicinae/bug-report-url.hpp"
#include "qml/raycast-store-detail-host.hpp"
#include "qml/vicinae-store-detail-host.hpp"
#include "qml/vicinae-store-view-host.hpp"
#include "root-search/extensions/extension-root-provider.hpp"
#include "settings-controller/settings-controller.hpp"
#include "services/toast/toast-service.hpp"
#include "config/config.hpp"
Expand Down Expand Up @@ -208,6 +215,7 @@ LauncherWindow::LauncherWindow(ApplicationContext &ctx, QObject *parent)
connect(nav, &NavigationController::viewPushed, this, [this](const BaseView *) {
m_actionPanel->close();
m_footerPanel->close();
emit footerStatusChanged();
});

connect(m_footerPanel, &ActionPanelController::openChanged, this, [this]() {
Expand Down Expand Up @@ -418,6 +426,7 @@ void LauncherWindow::handleCurrentViewChanged() {
if (m_atRoot != isRoot) {
m_atRoot = isRoot;
emit atRootChanged();
emit footerStatusChanged();
}

if (m_overrideWidth != 0 || m_overrideHeight != 0) {
Expand Down Expand Up @@ -558,7 +567,77 @@ void LauncherWindow::positionOnCursorScreen() {
m_window->setY(g.y() + (g.height() - m_window->height()) / 3);
}

void LauncherWindow::openFooterMenu() { m_footerPanel->toggle(true); }
bool LauncherWindow::footerStatusClickable() const {
auto *command = m_ctx.navigation->activeCommand();

return m_atRoot || command;
}

void LauncherWindow::openFooterMenu() {
if (m_footerPanel->isOpen()) {
m_footerPanel->close();
return;
}

if (m_atRoot) {
buildFooterMenu();
} else if (!buildCommandFooterMenu()) {
return;
}

m_footerPanel->toggle(true);
}

bool LauncherWindow::buildCommandFooterMenu() {
auto *active = m_ctx.navigation->activeCommand();
if (!active) return false;

auto id = active->uniqueId();
auto *manager = m_ctx.services->rootItemManager();

auto state = std::make_unique<ActionPanelState>();
state->setAutoSelectPrimary(false);
state->setTitle(active->repositoryDisplayName());
state->setId(QStringLiteral("command-footer-menu-%1").arg(active->extensionId()));

auto *commandSection = state->createSection(QStringLiteral("Command"));
auto metadata = manager->itemMetadata(id);
commandSection->addAction(new OpenItemPreferencesAction(id));
commandSection->addAction(new SetRootItemAliasAction(id));
commandSection->addAction(new ToggleItemAsFavorite(id, metadata.favorite));
commandSection->addAction(new CopyItemDeeplink(id));

auto *cmd = dynamic_cast<const ExtensionCommand *>(active);
if (!cmd) {
m_footerPanel->setActions(std::move(state));
return true;
}

auto *extensionSection = state->createSection(QStringLiteral("Extension"));

if (cmd->isVicinae()) {
extensionSection->addAction(
new StaticAction(QStringLiteral("View in Store"), ImageURL::builtin(BuiltinIcon::Cart),
[author = cmd->author(), name = cmd->repositoryName()](ApplicationContext *ctx) {
ctx->navigation->pushView(new VicinaeStoreDetailHost(author, name));
}));
} else if (cmd->isRaycast()) {
extensionSection->addAction(
new StaticAction(QStringLiteral("View in Store"), ImageURL::builtin(BuiltinIcon::Cart),
[author = cmd->author(), name = cmd->repositoryName()](ApplicationContext *ctx) {
ctx->navigation->pushView(new RaycastStoreDetailHost(author, name));
}));
}

extensionSection->addAction(
new CopyToClipboardAction(Clipboard::Text(cmd->path().c_str()), QStringLiteral("Copy Extension Path")));

auto *dangerSection = state->createSection();
dangerSection->addAction(new UninstallExtensionAction(cmd->extensionId()));

m_footerPanel->setActions(std::move(state));
return true;
}

void LauncherWindow::buildFooterMenu() {
auto state = std::make_unique<ActionPanelState>();
Expand Down
4 changes: 4 additions & 0 deletions src/server/src/qml/launcher-window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class LauncherWindow : public QObject {
Q_PROPERTY(QObject *commandViewHost READ commandViewHost NOTIFY commandViewHostChanged)
Q_PROPERTY(QString navigationTitle READ navigationTitle NOTIFY navigationStatusChanged)
Q_PROPERTY(ImageUrl navigationIcon READ navigationIcon NOTIFY navigationStatusChanged)
Q_PROPERTY(bool footerStatusClickable READ footerStatusClickable NOTIFY footerStatusChanged)
Q_PROPERTY(bool toastActive READ toastActive NOTIFY toastActiveChanged)
Q_PROPERTY(QString toastTitle READ toastTitle NOTIFY toastChanged)
Q_PROPERTY(QString toastMessage READ toastMessage NOTIFY toastChanged)
Expand Down Expand Up @@ -65,6 +66,7 @@ class LauncherWindow : public QObject {

QString navigationTitle() const { return m_navigationTitle; }
ImageUrl navigationIcon() const { return m_navigationIcon; }
bool footerStatusClickable() const;
bool toastActive() const { return m_toastActive; }
QString toastTitle() const { return m_toastTitle; }
QString toastMessage() const { return m_toastMessage; }
Expand Down Expand Up @@ -113,6 +115,7 @@ class LauncherWindow : public QObject {
void commandViewReplaced(const QUrl &componentUrl, const QVariantMap &properties);
void commandViewPopped();
void navigationStatusChanged();
void footerStatusChanged();
void toastActiveChanged();
void toastChanged();
void isLoadingChanged();
Expand All @@ -138,6 +141,7 @@ class LauncherWindow : public QObject {
void setExclusiveFocus(bool exclusive);
void updateLayerShellProps();
void buildFooterMenu();
bool buildCommandFooterMenu();

ApplicationContext &m_ctx;
ActionPanelController *m_actionPanel;
Expand Down
3 changes: 2 additions & 1 deletion src/server/src/qml/qml/Footer.qml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Item {

FooterNavStatus {
visible: !launcher.toastActive
clickable: launcher.atRoot
clickable: launcher.footerStatusClickable
rootMode: launcher.atRoot
availableWidth: parent.width
anchors.verticalCenter: parent.verticalCenter
onClicked: launcher.openFooterMenu()
Expand Down
21 changes: 12 additions & 9 deletions src/server/src/qml/qml/FooterNavStatus.qml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@ Item {
id: root

property bool clickable: false
property bool rootMode: false
property real availableWidth: 0

signal clicked

readonly property int buttonSize: 26
readonly property int buttonSize: 28
readonly property int backgroundPadding: root.rootMode ? 0 : 8
readonly property real textMaxWidth: Math.max(0, root.availableWidth - (navIcon.visible ? navIcon.width + row.spacing : 0))

implicitWidth: clickable ? 20 : row.implicitWidth
implicitWidth: root.rootMode ? 20 : row.implicitWidth
implicitHeight: Math.max(row.implicitHeight, clickable ? 26 : 0)

Rectangle {
visible: root.clickable && (mouseArea.containsMouse || footerPanel.open)
x: -Math.round((root.buttonSize - root.width) / 2)
x: root.rootMode ? -Math.round((root.buttonSize - root.width) / 2) : -root.backgroundPadding
anchors.verticalCenter: parent.verticalCenter
width: root.buttonSize
width: root.rootMode ? root.buttonSize : root.width + 2 * root.backgroundPadding
height: root.buttonSize
radius: 6
color: Theme.listItemHoverBg
Expand All @@ -33,8 +36,8 @@ Item {
id: navIcon
width: 20
height: 20
source: root.clickable ? Img.builtin("vicinae").withFillColor(Theme.textMuted) : launcher.navigationIcon
visible: root.clickable || launcher.navigationIcon.valid
source: root.rootMode ? Img.builtin("vicinae").withFillColor(Theme.textMuted) : launcher.navigationIcon
visible: root.rootMode || launcher.navigationIcon.valid
anchors.verticalCenter: parent.verticalCenter
}

Expand All @@ -44,17 +47,17 @@ Item {
font.family: Theme.fontFamily
font.pointSize: Theme.smallerFontSize
elide: Text.ElideRight
width: Math.max(0, root.availableWidth - (navIcon.visible ? navIcon.width + row.spacing : 0))
width: Math.min(implicitWidth, root.textMaxWidth)
anchors.verticalCenter: parent.verticalCenter
visible: launcher.navigationTitle !== ""
}
}

MouseArea {
id: mouseArea
x: -Math.round((root.buttonSize - root.width) / 2)
x: root.rootMode ? -Math.round((root.buttonSize - root.width) / 2) : -root.backgroundPadding
anchors.verticalCenter: parent.verticalCenter
width: root.buttonSize
width: root.rootMode ? root.buttonSize : root.width + 2 * root.backgroundPadding
height: root.buttonSize
enabled: root.clickable
hoverEnabled: enabled
Expand Down
Loading