diff --git a/buildroot-external/Config.in b/buildroot-external/Config.in index 1209d49f..aaadb48e 100644 --- a/buildroot-external/Config.in +++ b/buildroot-external/Config.in @@ -185,6 +185,7 @@ menu "Mycroft A.I. Plugins" endmenu menu "Mycroft A.I. Skills" source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/mycroft-skills-repo/Config.in" + source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/mycroft-skill-alarm/Config.in" source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/mycroft-skill-balena-wifi-setup/Config.in" source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/mycroft-skill-date-time/Config.in" source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/mycroft-skill-ovos-enclosure/Config.in" diff --git a/buildroot-external/configs/rpi4_64-gui_defconfig b/buildroot-external/configs/rpi4_64-gui_defconfig index 2d9b866f..ffbcab9c 100644 --- a/buildroot-external/configs/rpi4_64-gui_defconfig +++ b/buildroot-external/configs/rpi4_64-gui_defconfig @@ -596,6 +596,7 @@ BR2_PACKAGE_PYTHON_JARBAS_STT_PLUGIN_CHROMIUM=y BR2_PACKAGE_PYTHON_JARBAS_STT_PLUGIN_VOSK=y BR2_PACKAGE_PYTHON_JARBAS_WAKE_WORD_PLUGIN_PRECISE=y BR2_PACKAGE_MYCROFT_SKILLS_REPO=y +BR2_PACKAGE_MYCROFT_SKILL_ALARM=y BR2_PACKAGE_MYCROFT_SKILL_BALENA_WIFI_SETUP=y BR2_PACKAGE_MYCROFT_SKILL_DATE_TIME=y BR2_PACKAGE_MYCROFT_SKILL_OVOS_ENCLOSURE=y diff --git a/buildroot-external/package/mycroft-skill-alarm/0001-PR111.patch b/buildroot-external/package/mycroft-skill-alarm/0001-PR111.patch new file mode 100644 index 00000000..182f5203 --- /dev/null +++ b/buildroot-external/package/mycroft-skill-alarm/0001-PR111.patch @@ -0,0 +1,421 @@ +From 7601074617f28c5d0567e280afe98e18d5030db6 Mon Sep 17 00:00:00 2001 +From: Aditya Mehra +Date: Fri, 9 Apr 2021 17:42:35 +0530 +Subject: [PATCH 1/2] Add QML UI for alarm skill + +--- + __init__.py | 15 +++++ + ui/alarm.qml | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 202 insertions(+) + create mode 100644 ui/alarm.qml + +diff --git a/__init__.py b/__init__.py +index 55d77cd..6d8d5ae 100644 +--- a/__init__.py ++++ b/__init__.py +@@ -376,6 +376,7 @@ def handle_set_alarm(self, message): + ) + + self._show_alarm_anim(alarm_time) ++ self._show_alarm_ui(alarm_time, name) + self.enclosure.activate_mouth_events() + + def _get_alarm_name(self, utt): +@@ -707,6 +708,7 @@ def handle_delete(self, message): + self.speak_dialog( + "alarm.cancelled.desc" + recurring, data={"desc": desc} + ) ++ self.gui.remove_page("alarm.qml") + return + else: + self.speak_dialog("alarm.delete.cancelled") +@@ -723,6 +725,7 @@ def handle_delete(self, message): + ] + self._schedule() + self.speak_dialog("alarm.cancelled.multi", data={"count": total}) ++ self.gui.remove_page("alarm.qml") + return + elif not total: + # Failed to delete +@@ -900,6 +903,7 @@ def _stop_expired_alarm(self): + self.settings["alarm"] = curate_alarms( + self.settings["alarm"], 0 + ) # end any expired alarm ++ self.gui.remove_page("alarm.qml") + self._schedule() + return True + else: +@@ -937,6 +941,10 @@ def _alarm_expired(self): + name="Flash", + data={"alarm_time": alarm["timestamp"]}, + ) ++ alarm_timestamp = alarm.get("timestamp", "") ++ alarm_dt = get_alarm_local(timestamp=alarm_timestamp) ++ alarm_name = alarm.get("name", "") ++ self._show_alarm_ui(alarm_dt, alarm_name, alarm_exp=True) + + def __end_flash(self): + self.cancel_scheduled_event("Flash") +@@ -1010,6 +1018,13 @@ def _render_time(self, alarm_dt): + self.enclosure.mouth_display_png(png, x=x, y=2, refresh=False) + x += w + ++ def _show_alarm_ui(self, alarm_dt, alarm_name, alarm_exp=False): ++ self.gui["alarmTime"] = nice_time(alarm_dt, speech=False, ++ use_ampm=True) ++ self.gui["alarmName"] = alarm_name ++ self.gui["alarmExpired"] = alarm_exp ++ self.gui.show_page("alarm.qml") ++ + + def create_skill(): + """Create the Alarm Skill for Mycroft.""" +diff --git a/ui/alarm.qml b/ui/alarm.qml +new file mode 100644 +index 0000000..31ce990 +--- /dev/null ++++ b/ui/alarm.qml +@@ -0,0 +1,187 @@ ++import QtQuick 2.12 ++import QtQuick.Controls 2.5 ++import QtQuick.Layouts 1.3 ++import Mycroft 1.0 as Mycroft ++import org.kde.kirigami 2.11 as Kirigami ++import QtGraphicalEffects 1.0 ++ ++Mycroft.Delegate { ++ id: root ++ skillBackgroundColorOverlay: "black" ++ property bool alarmExpired: sessionData.alarmExpired ++ property color alarmColor: alarmExpired ? "#FFFFFF" : "#22A7F0" ++ leftPadding: 0 ++ rightPadding: 0 ++ topPadding: 0 ++ bottomPadding: 0 ++ ++ Rectangle { ++ id: leftRect ++ anchors.top: parent.top ++ anchors.topMargin: Math.round(centerRect.height * 0.085) ++ anchors.right: centerRect.left ++ anchors.rightMargin: Math.round(-centerRect.width * 0.340) ++ color: alarmColor ++ radius: width ++ width: parent.width / 6 ++ height: width ++ layer.enabled: true ++ layer.effect: OpacityMask { ++ maskSource: centerRect ++ } ++ } ++ ++ Rectangle { ++ id: rightRect ++ anchors.top: parent.top ++ anchors.topMargin: Math.round(centerRect.height * 0.085) ++ anchors.left: centerRect.right ++ anchors.leftMargin: Math.round(-centerRect.width * 0.340) ++ color: alarmColor ++ radius: width ++ width: parent.width / 6 ++ height: width ++ layer.enabled: true ++ layer.effect: OpacityMask { ++ maskSource: centerRect ++ } ++ } ++ ++ Rectangle { ++ id: rightBottomRect ++ anchors.top: centerRect.bottom ++ anchors.topMargin: -centerRect.height * 0.30 ++ anchors.left: centerRect.right ++ anchors.leftMargin: -centerRect.width * 0.20 ++ color: alarmColor ++ radius: 30 ++ rotation: -50 ++ z: 2 ++ width: centerRect.width * 0.16 ++ height: centerRect.height * 0.25 ++ } ++ ++ Rectangle { ++ id: leftBottomRect ++ anchors.top: centerRect.bottom ++ anchors.topMargin: -centerRect.height * 0.30 ++ anchors.right: centerRect.left ++ anchors.rightMargin: -centerRect.width * 0.20 ++ color: alarmColor ++ radius: 30 ++ rotation: 50 ++ z: 2 ++ width: centerRect.width * 0.16 ++ height: centerRect.height * 0.25 ++ } ++ ++ Rectangle { ++ id: centerRect ++ anchors.top: parent.top ++ anchors.topMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing ++ anchors.horizontalCenter: parent.horizontalCenter ++ color: "black" ++ radius: width ++ width: Math.min(Math.round(parent.width / 2.1050), 800) ++ height: width ++ ++ Rectangle { ++ id: centerRectInner ++ anchors.centerIn: parent ++ color: alarmColor ++ radius: width ++ width: Math.round(parent.width / 1.1180) ++ height: width ++ z: 5 ++ ++ Item { ++ anchors.fill: parent ++ ++ Label { ++ id: timeI ++ anchors.verticalCenter: parent.verticalCenter ++ anchors.horizontalCenter: parent.horizontalCenter ++ font.weight: Font.ExtraBold ++ font.pixelSize: parent.height * 0.375 ++ color: "black" ++ font.family: "Noto Sans SemiBold" ++ font.letterSpacing: 2 ++ text: sessionData.alarmTime.split(" ")[0] ++ z: 100 ++ ++ SequentialAnimation on opacity { ++ id: expireAnimation ++ running: alarmExpired ++ loops: Animation.Infinite ++ PropertyAnimation { ++ from: 1; ++ to: 0; ++ duration: 500 ++ } ++ ++ PropertyAnimation { ++ from: 0; ++ to: 1; ++ duration: 500 ++ } ++ } ++ } ++ ++ Label { ++ id: ampm ++ anchors.top: timeI.baseline ++ anchors.topMargin: 24 ++ anchors.horizontalCenter: parent.horizontalCenter ++ font.weight: Font.Bold ++ font.family: "Noto Sans Display" ++ font.pixelSize: parent.height * 0.14 ++ font.letterSpacing: 2 ++ color: "black" ++ text: sessionData.alarmTime.split(" ")[1] ++ z: 100 ++ ++ SequentialAnimation on opacity { ++ id: expireAnimation2 ++ running: alarmExpired ++ loops: Animation.Infinite ++ PropertyAnimation { ++ from: 1; ++ to: 0; ++ duration: 500 ++ } ++ ++ PropertyAnimation { ++ from: 0; ++ to: 1; ++ duration: 500 ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ Rectangle { ++ anchors.horizontalCenter: parent.horizontalCenter ++ anchors.bottom: parent.bottom ++ anchors.bottomMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing ++ width: centerRect.width ++ color: "transparent" ++ height: alarmLabel.contentHeight ++ ++ Label { ++ id: alarmLabel ++ color: "white" ++ width: parent.width ++ font.bold: true ++ horizontalAlignment: Text.AlignHCenter ++ verticalAlignment: Text.AlignVCenter ++ font.weight: Font.Bold ++ font.family: "Noto Sans Display SemiBold" ++ font.pixelSize: parent.width * 0.12 ++ font.letterSpacing: 2 ++ text: sessionData.alarmName ++ } ++ } ++} ++ + +From a219a3222110bd7f494b22113294bb29ffc4b6af Mon Sep 17 00:00:00 2001 +From: Aditya Mehra +Date: Fri, 30 Apr 2021 16:56:33 +0530 +Subject: [PATCH 2/2] Port to card delegate and match figma, fix text overflow + +--- + ui/alarm.qml | 52 +++++++++++++++++++++++++--------------------------- + 1 file changed, 25 insertions(+), 27 deletions(-) + +diff --git a/ui/alarm.qml b/ui/alarm.qml +index 31ce990..01ac372 100644 +--- a/ui/alarm.qml ++++ b/ui/alarm.qml +@@ -5,20 +5,16 @@ import Mycroft 1.0 as Mycroft + import org.kde.kirigami 2.11 as Kirigami + import QtGraphicalEffects 1.0 + +-Mycroft.Delegate { ++Mycroft.CardDelegate { + id: root +- skillBackgroundColorOverlay: "black" + property bool alarmExpired: sessionData.alarmExpired + property color alarmColor: alarmExpired ? "#FFFFFF" : "#22A7F0" +- leftPadding: 0 +- rightPadding: 0 +- topPadding: 0 +- bottomPadding: 0 ++ cardBackgoundOverlayColor: "black" + + Rectangle { + id: leftRect + anchors.top: parent.top +- anchors.topMargin: Math.round(centerRect.height * 0.085) ++ anchors.topMargin: Mycroft.Units.gridUnit - 2 + anchors.right: centerRect.left + anchors.rightMargin: Math.round(-centerRect.width * 0.340) + color: alarmColor +@@ -34,7 +30,7 @@ Mycroft.Delegate { + Rectangle { + id: rightRect + anchors.top: parent.top +- anchors.topMargin: Math.round(centerRect.height * 0.085) ++ anchors.topMargin: Mycroft.Units.gridUnit - 2 + anchors.left: centerRect.right + anchors.leftMargin: Math.round(-centerRect.width * 0.340) + color: alarmColor +@@ -55,10 +51,10 @@ Mycroft.Delegate { + anchors.leftMargin: -centerRect.width * 0.20 + color: alarmColor + radius: 30 +- rotation: -50 ++ rotation: -48 + z: 2 + width: centerRect.width * 0.16 +- height: centerRect.height * 0.25 ++ height: centerRect.height * 0.28 + } + + Rectangle { +@@ -69,20 +65,20 @@ Mycroft.Delegate { + anchors.rightMargin: -centerRect.width * 0.20 + color: alarmColor + radius: 30 +- rotation: 50 ++ rotation: 48 + z: 2 + width: centerRect.width * 0.16 +- height: centerRect.height * 0.25 ++ height: centerRect.height * 0.28 + } + + Rectangle { + id: centerRect + anchors.top: parent.top +- anchors.topMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing ++ anchors.topMargin: Mycroft.Units.gridUnit + 5 + anchors.horizontalCenter: parent.horizontalCenter + color: "black" + radius: width +- width: Math.min(Math.round(parent.width / 2.1050), 800) ++ width: Math.min(Math.round(parent.width / 2.480), 800) + height: width + + Rectangle { +@@ -99,16 +95,16 @@ Mycroft.Delegate { + + Label { + id: timeI +- anchors.verticalCenter: parent.verticalCenter +- anchors.horizontalCenter: parent.horizontalCenter ++ anchors.centerIn: parent + font.weight: Font.ExtraBold +- font.pixelSize: parent.height * 0.375 +- color: "black" +- font.family: "Noto Sans SemiBold" ++ font.pixelSize: timeI.text.length > 4 ? parent.width * 0.35 : parent.width * 0.40 ++ color: sessionData.alarmExpired ? "black" : "white" ++ font.family: "Noto Sans Display" ++ font.styleName: "bold" + font.letterSpacing: 2 + text: sessionData.alarmTime.split(" ")[0] + z: 100 +- ++ + SequentialAnimation on opacity { + id: expireAnimation + running: alarmExpired +@@ -130,16 +126,17 @@ Mycroft.Delegate { + Label { + id: ampm + anchors.top: timeI.baseline +- anchors.topMargin: 24 ++ anchors.topMargin: 15 + anchors.horizontalCenter: parent.horizontalCenter + font.weight: Font.Bold + font.family: "Noto Sans Display" +- font.pixelSize: parent.height * 0.14 ++ font.styleName: "bold" ++ font.pixelSize: parent.height * 0.175 + font.letterSpacing: 2 +- color: "black" ++ color: sessionData.alarmExpired ? "black" : "white" + text: sessionData.alarmTime.split(" ")[1] + z: 100 +- ++ + SequentialAnimation on opacity { + id: expireAnimation2 + running: alarmExpired +@@ -162,9 +159,10 @@ Mycroft.Delegate { + } + + Rectangle { ++ id: alarmLabelBox + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom +- anchors.bottomMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing ++ anchors.bottomMargin: Mycroft.Units.gridUnit * 2 - 5 + width: centerRect.width + color: "transparent" + height: alarmLabel.contentHeight +@@ -177,11 +175,11 @@ Mycroft.Delegate { + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.weight: Font.Bold +- font.family: "Noto Sans Display SemiBold" ++ font.family: "Noto Sans Display" ++ font.styleName: "SemiBold" + font.pixelSize: parent.width * 0.12 + font.letterSpacing: 2 + text: sessionData.alarmName + } + } + } +- diff --git a/buildroot-external/package/mycroft-skill-alarm/Config.in b/buildroot-external/package/mycroft-skill-alarm/Config.in new file mode 100644 index 00000000..dccc42c0 --- /dev/null +++ b/buildroot-external/package/mycroft-skill-alarm/Config.in @@ -0,0 +1,7 @@ +config BR2_PACKAGE_MYCROFT_SKILL_ALARM + bool "mycroft-skill-alarm" + help + Mycroft AI official Alarm Skill - Set single + and recurring alarms, with a choice of alarm sounds + + https://github.com/MycroftAI/skill-alarm diff --git a/buildroot-external/package/mycroft-skill-alarm/mycroft-skill-alarm.mk b/buildroot-external/package/mycroft-skill-alarm/mycroft-skill-alarm.mk new file mode 100644 index 00000000..95e9a27c --- /dev/null +++ b/buildroot-external/package/mycroft-skill-alarm/mycroft-skill-alarm.mk @@ -0,0 +1,20 @@ +################################################################################ +# +# mycroft-skill-alarm +# +################################################################################ + +MYCROFT_SKILL_ALARM_VERSION = 7bce0ee39867b3e1cf81c33c81d7830afd34e1b3 +MYCROFT_SKILL_ALARM_SITE = git://github.com/MycroftAI/skill-alarm +MYCROFT_SKILL_ALARM_SITE_METHOD = git +MYCROFT_SKILL_ALARM_DIRLOCATION = home/mycroft/.local/share/mycroft/skills +MYCROFT_SKILL_ALARM_DIRNAME = mycroft-alarm.mycroftai + +define MYCROFT_SKILL_ALARM_INSTALL_TARGET_CMDS + mkdir -p $(TARGET_DIR)/$(MYCROFT_SKILL_ALARM_DIRLOCATION)/$(MYCROFT_SKILL_ALARM_DIRNAME) + cp -dpfr $(@D)/* $(TARGET_DIR)/$(MYCROFT_SKILL_ALARM_DIRLOCATION)/$(MYCROFT_SKILL_ALARM_DIRNAME) + cp -dpfr $(MYCROFT_SKILL_ALARM_DL_DIR)/git/.git* \ + $(TARGET_DIR)/$(MYCROFT_SKILL_ALARM_DIRLOCATION)/$(MYCROFT_SKILL_ALARM_DIRNAME) +endef + +$(eval $(generic-package))