From: David Llewellyn-Jones Date: Mon, 16 Jul 2018 22:29:40 +0000 (+0100) Subject: Add flashy spiral timer to cover X-Git-Url: https://www.flypig.org.uk/git/?p=harbour-pedalo.git;a=commitdiff_plain;h=48a4da912f9df07681ba68d33475e1d43cfab571 Add flashy spiral timer to cover --- diff --git a/generate.sh b/generate.sh index 7233e82..fcff0a3 100755 --- a/generate.sh +++ b/generate.sh @@ -36,3 +36,6 @@ generate 303 86 "pedalo-title" # Generate buttons generate 246 200 "button-journey-add button-journey-start button-journey-finish button-list button-stats" +# Generate cover action icons +generate 32 32 "icon-cover-journey-finish icon-cover-journey-start" + diff --git a/harbour-pedalo.pro b/harbour-pedalo.pro index 0b88acc..ce9b2c7 100644 --- a/harbour-pedalo.pro +++ b/harbour-pedalo.pro @@ -50,7 +50,9 @@ DISTFILES += qml/harbour-pedalo.qml \ qml/components/InfoRow.qml \ qml/pages/JourneyEdit.qml \ qml/pages/JourneyInfo.qml \ - qml/components/BarButton.qml + qml/components/BarButton.qml \ + qml/cover/ClockView.qml \ + qml/cover/LargeItem.qml SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 256x256 diff --git a/inputs/icon-cover-journey-finish.svg b/inputs/icon-cover-journey-finish.svg new file mode 100644 index 0000000..7741437 --- /dev/null +++ b/inputs/icon-cover-journey-finish.svg @@ -0,0 +1,79 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/inputs/icon-cover-journey-start.svg b/inputs/icon-cover-journey-start.svg new file mode 100644 index 0000000..e754855 --- /dev/null +++ b/inputs/icon-cover-journey-start.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/qml/cover/ClockView.qml b/qml/cover/ClockView.qml new file mode 100644 index 0000000..88652b2 --- /dev/null +++ b/qml/cover/ClockView.qml @@ -0,0 +1,99 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +Item { + id: root + + property QtObject timerClock + + // Size of the clock border decoration as a fraction of the radius + property real _faceRadiusBase: 84 + property real _faceHourLength: 14.736 / _faceRadiusBase + + Image { + id: clockFace + + anchors.fill: parent + fillMode: Image.PreserveAspectFit + source: "image://theme/graphic-clock-face-3" + } + + ShaderEffect { + id: timerVisualization + + anchors.fill: clockFace + + visible: stopwatch.update + + onVisibleChanged: { + _updateTimerVisualization() + } + + property int _seconds: stopwatch.seconds + on_SecondsChanged: _updateTimerVisualization() + + property real outerRadius: 1 + property real innerRadius: 1 - _faceHourLength + property real endAngle + property real loopRadius: outerRadius / 10 + property real count + + property color highlightColor: Theme.rgba(Theme.highlightColor, 0.75) + + function _updateTimerVisualization() { + if (stopwatch.fast) { + count = _seconds + } + else { + count = Math.floor(_seconds / 60) + } + + endAngle = 2 * Math.PI * count / 60 + innerRadius = outerRadius - loopRadius * (parseInt(count / 60) + 1) + } + + vertexShader: " + uniform highp mat4 qt_Matrix; + attribute highp vec4 qt_Vertex; + attribute highp vec2 qt_MultiTexCoord0; + varying highp vec2 coord; + void main() { + coord = qt_MultiTexCoord0; + gl_Position = qt_Matrix * qt_Vertex; + }" + fragmentShader: " + varying highp vec2 coord; + uniform lowp float qt_Opacity; + uniform lowp float outerRadius; + uniform lowp float innerRadius; + uniform lowp float endAngle; + uniform lowp float loopRadius; + uniform lowp vec4 highlightColor; + uniform lowp float count; + + lowp float PI = 3.14159265358979323846264; + + void main() { + highp vec2 vector = 2.0*(coord - vec2(0.5, 0.5)); + lowp float radius = length(vector); + lowp float angle = atan(vector.y, vector.x) + PI/2.0; + angle += angle < 0.0 ? 2.0*PI : 0.0; + + lowp float minRadius = outerRadius - ((count / 60.0) + 1.0) * loopRadius + (loopRadius * angle / (2.0 * PI)); + lowp float maxRadius = outerRadius - ((mod(count, 60.0) / 60.0) + 1.0) * loopRadius + (loopRadius * angle / (2.0 * PI)); + + if (angle < 2.0 * PI * mod(count, 60.0) / 60.0) { + maxRadius += loopRadius; + } + + if (radius >= minRadius && radius < maxRadius) { + if (mod(radius - minRadius, loopRadius) > 0.2 * loopRadius) { + gl_FragColor = highlightColor; + return; + } + } + gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); + return; + }" + } +} diff --git a/qml/cover/CoverPage.qml b/qml/cover/CoverPage.qml index fc562d5..a4a911b 100644 --- a/qml/cover/CoverPage.qml +++ b/qml/cover/CoverPage.qml @@ -1,22 +1,111 @@ import QtQuick 2.0 import Sailfish.Silica 1.0 +import harbour.pedalo.settings 1.0 CoverBackground { - Label { - id: label - anchors.centerIn: parent - text: qsTr("My Cover") + id: root + property bool update: status === Cover.Active && currentStatus.cycling + + onUpdateChanged: { + stopwatch.updateseconds() + stopwatchtrigger.restart() + } + + Item { + id: stopwatch + property int seconds: 0 + property int fast: seconds < 60 * 10 + property bool update: root.update + + Timer { + id: stopwatchtrigger + interval: stopwatch.fast ? 200 : 5000 + running: root.update + repeat: true + triggeredOnStart: true + onTriggered: { + stopwatch.updateseconds() + } + } + + function updateseconds() { + stopwatch.seconds = (new Date().getTime() - currentStatus.startTime) / 1000 + } + } + + Item { + id: contents + + width: Theme.coverSizeLarge.width + height: Theme.coverSizeLarge.height + property real xScale: root.width / contents.width + + transform: Scale { + xScale: contents.xScale + yScale: root.height / contents.height + } + + ClockView { + id: clockView + + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: Theme.paddingLarge + } + height: width + } + + LargeItem { + id: stopwatchView + + anchors { + top: clockView.bottom + topMargin: Theme.paddingMedium + leftMargin: Theme.paddingLarge + rightMargin: Theme.paddingLarge + } + + textVisible: root.update + + title: qsTr("Pedalo") + + text: { + if (stopwatch.seconds < 60) { + return qsTr("%n seconds", "", stopwatch.seconds) + } else if (stopwatch.seconds < 60*60) { + return qsTr("%1 minutes").arg(Math.floor(stopwatch.seconds/60)) + } else { + var minutes = Math.floor(stopwatch.seconds/60) + var hours = Math.floor(minutes/60) + minutes = minutes % 60 + return qsTrId("%1h %2min").arg(hours).arg(minutes) + } + } + } } CoverActionList { id: coverAction CoverAction { - iconSource: "image://theme/icon-cover-next" - } + iconSource: currentStatus.cycling ? Settings.getImageUrl("icon-cover-journey-finish") : Settings.getImageUrl("icon-cover-journey-start") + onTriggered: { + if (currentStatus.cycling) { + app.activate() + app.showMainPage(PageStackAction.Immediate) - CoverAction { - iconSource: "image://theme/icon-cover-pause" + var dialog = pageStack.push(Qt.resolvedUrl("../pages/JourneyEdit.qml"), {title: "Finish journey", start: journeymodel.epochToDateTime(currentStatus.startTime), duration: currentStatus.getDuration()}) + + dialog.accepted.connect(function() { + currentStatus.cycling = false + }) + } + else { + currentStatus.startJourney() + } + } } } } diff --git a/qml/cover/LargeItem.qml b/qml/cover/LargeItem.qml new file mode 100644 index 0000000..9d8d887 --- /dev/null +++ b/qml/cover/LargeItem.qml @@ -0,0 +1,36 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +Column { + property alias title: titleLabel.text + property alias titleVisible: titleLabel.visible + property alias text: subLabel.text + property alias textVisible: subLabel.visible + + anchors { + left: parent ? parent.left : undefined + right: parent ? parent.right : undefined + } + + Label { + id: titleLabel + + width: Math.min(parent.width, implicitWidth) + x: (parent.width - width) / 2 + + color: Theme.primaryColor + font.pixelSize: Theme.fontSizeLarge + truncationMode: TruncationMode.Fade + } + + Label { + id: subLabel + + width: Math.min(parent.width, implicitWidth) + x: (parent.width - width) / 2 + + color: Theme.highlightColor + font.pixelSize: Theme.fontSizeExtraSmall + truncationMode: TruncationMode.Fade + } +} diff --git a/qml/harbour-pedalo.qml b/qml/harbour-pedalo.qml index 22ccbbc..3194b9e 100644 --- a/qml/harbour-pedalo.qml +++ b/qml/harbour-pedalo.qml @@ -5,7 +5,19 @@ import harbour.pedalo.settings 1.0 ApplicationWindow { + id: app initialPage: Component { MainPage { } } cover: Qt.resolvedUrl("cover/CoverPage.qml") allowedOrientations: defaultAllowedOrientations + + function showMainPage(operationType) { + var first = pageStack.currentPage + var temp = pageStack.previousPage(pageStack.currentPage) + while (temp) { + first = temp + temp = pageStack.previousPage(temp) + } + + pageStack.pop(first, operationType) + } } diff --git a/translations/harbour-pedalo-de.ts b/translations/harbour-pedalo-de.ts index 18ba179..801b26d 100644 --- a/translations/harbour-pedalo-de.ts +++ b/translations/harbour-pedalo-de.ts @@ -1,6 +1,13 @@ + + + + + + + About @@ -39,8 +46,18 @@ CoverPage - My Cover - Mein Cover + Pedalo + + + + %n seconds + + + + + + %1 minutes + diff --git a/translations/harbour-pedalo.ts b/translations/harbour-pedalo.ts index 27f1377..801b26d 100644 --- a/translations/harbour-pedalo.ts +++ b/translations/harbour-pedalo.ts @@ -1,6 +1,13 @@ + + + + + + + About @@ -39,7 +46,17 @@ CoverPage - My Cover + Pedalo + + + + %n seconds + + + + + + %1 minutes