Skip to content

Commit c217af2

Browse files
authored
Merge pull request #625 from Kermut572/main
Add ru-menu plugin
2 parents a21e93c + a5767dd commit c217af2

7 files changed

Lines changed: 321 additions & 0 deletions

File tree

ru-menu/BarWidget.qml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import QtQuick
2+
import QtQuick.Layouts
3+
import Quickshell
4+
import qs.Commons
5+
import qs.Widgets
6+
import qs.Services.UI
7+
import qs.Services.System
8+
9+
Item {
10+
id: root
11+
12+
// Plugin API (injected by PluginService)
13+
property var pluginApi: null
14+
property var cfg: pluginApi?.pluginSettings || ({})
15+
property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({})
16+
17+
// Required properties for bar widgets
18+
property ShellScreen screen
19+
property string widgetId: ""
20+
property string section: ""
21+
property int sectionWidgetIndex: -1
22+
property int sectionWidgetsCount: 0
23+
24+
readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screen?.name)
25+
readonly property real contentWidth: row.implicitWidth + Style.marginM * 2
26+
readonly property real contentHeight: capsuleHeight
27+
28+
readonly property color iconColor: Color.resolveColorKey(cfg.iconColor ?? defaults.iconColor ?? "none")
29+
30+
implicitWidth: row.implicitWidth + Style.marginM * 2
31+
implicitHeight: Style.barHeight
32+
33+
Rectangle {
34+
id: visualCapsule
35+
x: Style.pixelAlignCenter(parent.width, width)
36+
y: Style.pixelAlignCenter(parent.height, height)
37+
width: root.contentWidth
38+
height: root.contentHeight
39+
color: mouseArea.containsMouse ? Color.mHover : Style.capsuleColor
40+
radius: Style.radiusL
41+
border.color: Style.capsuleBorderColor
42+
border.width: Style.capsuleBorderWidth
43+
44+
RowLayout {
45+
id: row
46+
anchors.centerIn: parent
47+
spacing: Style.marginS
48+
49+
NIcon {
50+
icon: "burger"
51+
color: mouseArea.containsMouse ? Color.mOnHover : root.iconColor
52+
}
53+
}
54+
}
55+
56+
MouseArea {
57+
id: mouseArea
58+
anchors.fill: parent
59+
hoverEnabled: true
60+
cursorShape: Qt.PointingHandCursor
61+
62+
onClicked: {
63+
if (pluginApi) {
64+
pluginApi.openPanel(root.screen, root);
65+
}
66+
}
67+
68+
onEntered: {
69+
TooltipService.show(root, pluginApi?.tr("widget.tooltip"), BarService.getTooltipDirection());
70+
}
71+
72+
onExited: {
73+
TooltipService.hide();
74+
}
75+
}
76+
}

ru-menu/Panel.qml

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import QtQuick
2+
import QtQuick.Layouts
3+
import qs.Commons
4+
import qs.Widgets
5+
6+
Item {
7+
id: root
8+
9+
// https://stackoverflow.com/questions/4156434/javascript-get-the-first-day-of-the-week-from-current-date
10+
function getMonday(d) {
11+
d = new Date(d);
12+
var day = d.getDay(), diff = d.getDate() - day + (day == 0 ? -6 : 1); // adjust when day is sunday
13+
return new Date(d.setDate(diff));
14+
}
15+
16+
function getWeekFormat(d) {
17+
const date = d.getUTCDate().toString().padStart(2, '0') + "/" + (d.getUTCMonth() + 1).toString().padStart(2, '0') + "/" + d.getUTCFullYear();
18+
return pluginApi?.tr("panel.week-format", {
19+
date: date
20+
});
21+
}
22+
23+
function getMenuUrl(d) {
24+
const day = d.getUTCDate().toString().padStart(2, '0');
25+
const month = (d.getUTCMonth() + 1).toString().padStart(2, '0');
26+
const year = d.getUTCFullYear().toString().slice(-2);
27+
return "https://www.uclouvain.be/fr/system/files/uclouvain_assetmanager/groups/cms-editors-resto-u/" + day + month + year + ".jpeg";
28+
}
29+
30+
// Plugin API (injected by PluginPanelSlot)
31+
property var pluginApi: null
32+
33+
// SmartPanel properties (required for panel behavior)
34+
readonly property var geometryPlaceholder: panelContainer
35+
readonly property bool allowAttach: true
36+
37+
// Preferred dimensions
38+
property real contentPreferredWidth: 500 * Style.uiScaleRatio
39+
property real contentPreferredHeight: 540 * Style.uiScaleRatio
40+
41+
property date currentMonday: getMonday(new Date())
42+
property string dateString: getWeekFormat(currentMonday)
43+
44+
anchors.fill: parent
45+
46+
Rectangle {
47+
id: panelContainer
48+
anchors.fill: parent
49+
color: "transparent"
50+
51+
ColumnLayout {
52+
id: dateSelector
53+
54+
anchors {
55+
fill: parent
56+
margins: Style.marginM
57+
}
58+
spacing: Style.marginM
59+
Rectangle {
60+
id: headerRect
61+
radius: Style.marginM
62+
Layout.preferredWidth: parent.width
63+
Layout.preferredHeight: 40 * Style.uiScaleRatio
64+
color: "transparent"
65+
border.color: Color.mPrimary
66+
67+
NButton {
68+
anchors.left: parent.left
69+
anchors.leftMargin: Style.marginM
70+
anchors.verticalCenter: parent.verticalCenter
71+
72+
width: 20 * Style.uiScaleRatio
73+
height: 20 * Style.uiScaleRatio
74+
75+
NIcon {
76+
icon: "caret-left"
77+
anchors.centerIn: parent
78+
}
79+
80+
onClicked: {
81+
currentMonday = getMonday(new Date(currentMonday.setDate(currentMonday.getDate() - 7)));
82+
dateString = getWeekFormat(currentMonday);
83+
menuImage.loaded = false;
84+
menuImage.source = getMenuUrl(currentMonday);
85+
loadingOverlay.visible = true;
86+
errorOverlay.visible = false;
87+
rotationAnimation.running = true;
88+
}
89+
}
90+
91+
NText {
92+
anchors.centerIn: parent
93+
text: dateString
94+
}
95+
96+
NButton {
97+
anchors.right: parent.right
98+
anchors.rightMargin: Style.marginM
99+
anchors.verticalCenter: parent.verticalCenter
100+
101+
width: 20 * Style.uiScaleRatio
102+
height: 20 * Style.uiScaleRatio
103+
104+
NIcon {
105+
icon: "caret-right"
106+
anchors.centerIn: parent
107+
}
108+
109+
onClicked: {
110+
currentMonday = getMonday(new Date(currentMonday.setDate(currentMonday.getDate() + 7)));
111+
dateString = getWeekFormat(currentMonday);
112+
menuImage.loaded = false;
113+
menuImage.source = getMenuUrl(currentMonday);
114+
loadingOverlay.visible = true;
115+
errorOverlay.visible = false;
116+
rotationAnimation.running = true;
117+
}
118+
}
119+
}
120+
121+
Item {
122+
id: imageContainer
123+
Layout.fillWidth: true
124+
Layout.fillHeight: true
125+
126+
NBox {
127+
id: loadingOverlay
128+
anchors.centerIn: parent
129+
visible: !menuImage.loaded
130+
color: "transparent"
131+
132+
NIcon {
133+
icon: "refresh"
134+
font.pixelSize: 48
135+
anchors.centerIn: parent
136+
RotationAnimation on rotation {
137+
id: rotationAnimation
138+
loops: Animation.Infinite
139+
duration: 1000
140+
from: 0
141+
to: 360
142+
}
143+
}
144+
}
145+
146+
NBox {
147+
id: errorOverlay
148+
anchors.centerIn: parent
149+
visible: false
150+
color: "transparent"
151+
152+
NText {
153+
text: pluginApi?.tr("panel.error.no-menu")
154+
anchors.centerIn: parent
155+
}
156+
}
157+
158+
Image {
159+
id: menuImage
160+
property bool loaded: false
161+
anchors.fill: parent
162+
fillMode: Image.PreserveAspectFit
163+
source: getMenuUrl(currentMonday)
164+
cache: true
165+
asynchronous: true
166+
167+
onStatusChanged: {
168+
if (status === Image.Ready) {
169+
loaded = true;
170+
rotationAnimation.running = false;
171+
loadingOverlay.visible = false;
172+
errorOverlay.visible = false;
173+
} else if (status === Image.Error) {
174+
loaded = false;
175+
rotationAnimation.running = false;
176+
loadingOverlay.visible = false;
177+
errorOverlay.visible = true;
178+
}
179+
}
180+
}
181+
}
182+
}
183+
}
184+
}

ru-menu/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# RU Menu
2+
3+
A simple plugin showing UCLouvain's Restaurants Universitaires weekly menus from the comfort of the Noctalia bar.
4+
5+
## Features
6+
7+
- **Current Menu**: By default, the current weekly menu is shown when opening the panel from the widget.
8+
- **Past and Future Menus**: See menus from past weeks (or years!) and even future menus (when available).
9+
10+
## Usage
11+
12+
1. Add the **RU Menu** widget to your bar.
13+
2. Click the burger icon in the bar to open the panel.
14+
3. Use the left/right arrows in the panel header to select a week.
15+
16+
## Troubleshooting
17+
18+
- **Failed to load menu**: Occurs when there is not (yet) a menu for the selected week.

ru-menu/i18n/en.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"panel": {
3+
"error": {
4+
"no-menu": "Failed to load menu"
5+
},
6+
"week-format": "Week of {date}"
7+
},
8+
"widget": {
9+
"tooltip": "Weekly menu"
10+
}
11+
}

ru-menu/i18n/fr.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"panel": {
3+
"error": {
4+
"no-menu": "Échec du chargement du menu"
5+
},
6+
"week-format": "Semaine du {date}"
7+
},
8+
"widget": {
9+
"tooltip": "Menu de la semaine"
10+
}
11+
}

ru-menu/manifest.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"id": "ru-menu",
3+
"name": "RU Menu",
4+
"version": "1.0.0",
5+
"minNoctaliaVersion": "3.6.0",
6+
"author": "Kermut572",
7+
"license": "MIT",
8+
"repository": "https://github.com/noctalia-dev/noctalia-plugins",
9+
"description": "A simple plugin that fetches the current, past, and future weeks menu for UCLouvain's Restaurants Universitaires",
10+
"tags": ["Bar", "Panel"],
11+
"entryPoints": {
12+
"barWidget": "BarWidget.qml",
13+
"panel": "Panel.qml"
14+
},
15+
"dependencies": {
16+
"plugins": []
17+
},
18+
"metadata": {
19+
"defaultSettings": {}
20+
}
21+
}

ru-menu/preview.png

190 KB
Loading

0 commit comments

Comments
 (0)