Advertisement
Guest User

patched NotificationPreview.qml

a guest
Mar 3rd, 2018
434
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
QML 33.55 KB | None | 0 0
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Jolla Ltd.
  4. ** Contact: Vesa Halttunen <vesa.halttunen@jollamobile.com>
  5. **
  6. ****************************************************************************/
  7.  
  8. import QtQuick 2.0
  9. import Sailfish.Silica 1.0
  10. import Sailfish.Lipstick 1.0
  11. import com.jolla.lipstick 0.1
  12. import org.nemomobile.lipstick 0.1
  13. import org.nemomobile.thumbnailer 1.0
  14. import org.nemomobile.devicelock 1.0
  15. import "../systemwindow"
  16. import Nemo.Configuration 1.0
  17.  
  18. SystemWindow {
  19.     id: notificationWindow
  20.  
  21.     property QtObject notification: notificationPreviewPresenter.notification
  22.     property bool showNotification: notification != null && (notification.previewBody || notification.previewSummary)
  23.     property string summaryText: showNotification ? notification.previewSummary : ''
  24.     property string bodyText: showNotification ? notification.previewBody : ''
  25.     property bool popupPresentation: state == "showPopup" || state == "hidePopup"
  26.     property string iconSource: showNotification ? (popupPresentation ? (notification.previewIcon || notification.icon || notification.appIcon)
  27.                                                                       : (notification.previewIcon || notification.icon)) : ""
  28.     property real statusBarPushDownY: bannerArea.y + bannerArea.height
  29.  
  30.     property string iconUrl: {
  31.         if (iconSource.length) {
  32.             if (iconSource.indexOf("http") === 0) {
  33.                 return iconSource
  34.             } else if (iconSource.indexOf("/") === 0) {
  35.                 return "image://nemoThumbnail/" + iconSource
  36.             } else if (iconSource.indexOf("image://theme/") === 0) {
  37.                 return iconSource
  38.             } else {
  39.                 return "image://theme/" + iconSource
  40.             }
  41.         }
  42.         return ''
  43.     }
  44.  
  45.     property bool _invoked
  46.  
  47.     Binding {
  48.         // Invocation typically closes the notification, so bind the current values
  49.         // to prevent unwanted changes to these properties
  50.         when: notificationWindow._invoked
  51.         target: notificationWindow
  52.         property: "summaryText"
  53.         value: notificationWindow.summaryText
  54.     }
  55.     Binding {
  56.         when: notificationWindow._invoked
  57.         target: notificationWindow
  58.         property: "bodyText"
  59.         value: notificationWindow.bodyText
  60.     }
  61.     Binding {
  62.         when: notificationWindow._invoked
  63.         target: notificationWindow
  64.         property: "iconUrl"
  65.         value: notificationWindow.iconUrl
  66.     }
  67.  
  68.     function firstLine(str) {
  69.         var i = str.indexOf("\n")
  70.         if (i >= 0) {
  71.             return str.substr(0, i)
  72.         }
  73.         return str
  74.     }
  75.  
  76.     opacity: 0
  77.     visible: false
  78.  
  79.     property bool removeRequested: false
  80.  
  81.     function notificationAction() {
  82.         if (notification) {
  83.             notificationWindow._invoked = true
  84.             notification.actionInvoked("default")
  85.  
  86.             // Also go to the switcher in case the screen was locked at invocation
  87.             Lipstick.compositor.unlock()
  88.         }
  89.     }
  90.  
  91.     function dismissPreview() {
  92.  
  93.         forceHideTimer.stop()
  94.         notificationWindow.notificationExpired()
  95.     }
  96.  
  97.     function removeNotification() {
  98.         removeRequested = true
  99.  
  100.         forceHideTimer.stop()
  101.         notificationWindow.notificationExpired()
  102.     }
  103.  
  104.     ConfigurationGroup {
  105.         id: previewSettings
  106.         path: "/desktop/lipstick-jolla-home/notification-preview"
  107.  
  108.         property int style: 0
  109.         property int corner_radius: {Theme.paddingSmall}
  110.         property int margin: 0
  111.         property int position: 0
  112.         property int min_width: 0
  113.         property int max_width: 57
  114.         property int timeout: 5000
  115.         property int click_action: 1
  116.         property int left_swipe_action: 0
  117.         property int right_swipe_action: 0
  118.         property int down_swipe_action: 0
  119.     }
  120.  
  121.     MouseArea {
  122.         id: popupArea
  123.  
  124.  
  125.         property bool down: pressed && containsMouse
  126.         property real textOpacity: 0
  127.         property color textColor: down || drag.active ? Theme.highlightColor : Theme.primaryColor
  128.         property real maxDisplayWidth: previewSettings.max_width / 100 * Screen.height
  129.         property real minDisplayWidth: previewSettings.min_width / 100 * Screen.height
  130.         property real displayWidth: body.width + bodyContainer.x + Theme.paddingMedium > minDisplayWidth
  131.                                     || summary.contentWidth + summary.x + Theme.paddingMedium > minDisplayWidth
  132.                                     ? Math.min((body.width > summary.contentWidth ? body.width : summary.contentWidth)
  133.                                                + bodyContainer.x + Theme.paddingMedium, notificationWindow.width
  134.                                                - (previewSettings.style !== 2 ? 2*previewSettings.margin : 0), maxDisplayWidth)
  135.                                     : Math.min(minDisplayWidth, notificationWindow.width
  136.                                                - (previewSettings.style !== 2 ? 2*previewSettings.margin : 0))
  137.         property bool notificationShownNSteady: false
  138.  
  139.         objectName: "NotificationPreview_popupArea"
  140.         anchors {
  141.             top: parent.top
  142.             horizontalCenter: previewSettings.position === 0 ? parent.horizontalCenter : undefined
  143.             left: previewSettings.position === 1 ? parent.left : undefined
  144.             right: previewSettings.position === 2 ? parent.right : undefined
  145.             margins: previewSettings.style !== 2 ? previewSettings.margin : 0
  146.         }
  147.         width: displayWidth
  148.         height: Math.max(Theme.itemSizeSmall, summary.y*2 + summary.height + bodyContainer.anchors.topMargin + bodyContainer.height)
  149.         opacity: 0
  150.  
  151.         onWidthChanged: {
  152.             if (notificationShownNSteady) {
  153.                 scrollAnimation.reset()
  154.                 if (scrollAnimation.initialize(body, bodyContainer)) {
  155.                     scrollAnimation.start()
  156.                 }
  157.             }
  158.         }
  159.         onClicked: {
  160.             if (clickAction !== undefined) {
  161.                 clickAction()
  162.             }
  163.         }
  164.         onDownChanged: {
  165.             if (!down) {
  166.                 if (!notificationTimer.running && !forceHideTimer.running) {
  167.                     notificationWindow.notificationExpired()
  168.                 }
  169.             }
  170.         }
  171.  
  172.         SequentialAnimation {
  173.             id: dragAnimation
  174.             NumberAnimation {
  175.                 id: slideAnimation
  176.                 property: "x"
  177.                 target: popupIcon
  178.             }
  179.             ScriptAction {
  180.                 script: {
  181.                     if (Math.abs(slideAnimation.to) === popupArea.drag.maximumX) {
  182.                         notificationWindow.state = ""
  183.                         notificationWindow.notificationExpired()
  184.                     }
  185.                 }
  186.             }
  187.         }
  188.  
  189.         Rectangle {
  190.             anchors.fill: parent
  191.             radius: previewSettings.style === 2 && (transpose && parent.width === Screen.height || !transpose && parent.width === Screen.width)
  192.                     ? 0 : previewSettings.corner_radius
  193.             color: popupArea.down || popupArea.drag.active ? Qt.tint(Qt.tint(Theme.highlightBackgroundColor, Qt.rgba(0, 0, 0, 0.2)), Theme.rgba(Theme.highlightDimmerColor, 0.4))
  194.                         : Qt.tint(Theme.highlightBackgroundColor, Qt.rgba(0, 0, 0, 0.2))
  195.             clip: true
  196.  
  197.             Behavior on radius {
  198.                 NumberAnimation {duration: 100; easing.type: Easing.InOutQuad}
  199.             }
  200.  
  201.             Rectangle {
  202.                 height: parent.radius
  203.                 width: height
  204.                 color: parent.color
  205.                 anchors.top: parent.top
  206.                 anchors.left: parent.left
  207.                 visible: previewSettings.style > 0 && previewSettings.style < 4
  208.             }
  209.             Rectangle {
  210.                 height: parent.radius
  211.                 width: height
  212.                 color: parent.color
  213.                 anchors.top: parent.top
  214.                 anchors.right: parent.right
  215.                 visible: previewSettings.style === 1 || previewSettings.style === 2 || previewSettings.style === 4
  216.             }
  217.             Rectangle {
  218.                 height: parent.radius
  219.                 width: height
  220.                 color: parent.color
  221.                 anchors.bottom: parent.bottom
  222.                 anchors.left: parent.left
  223.                 visible: previewSettings.style === 1 || previewSettings.style === 2 && previewSettings.position === 1
  224.             }
  225.             Rectangle {
  226.                 height: parent.radius
  227.                 width: height
  228.                 color: parent.color
  229.                 anchors.bottom: parent.bottom
  230.                 anchors.right: parent.right
  231.                 visible: previewSettings.style === 1 || previewSettings.style === 2 && previewSettings.position === 2
  232.             }
  233.  
  234.             Item {
  235.                 id: contentBase
  236.                 height: parent.height
  237.                 width: parent.width
  238.  
  239.                 Label {
  240.                     id: summary
  241.  
  242.                     anchors {
  243.                         top: parent.top
  244.                         topMargin: Theme.paddingMedium/2
  245.                         left: popupIcon.right
  246.                         leftMargin: Theme.paddingMedium
  247.                         right: parent.right
  248.                         rightMargin: Theme.paddingMedium
  249.                     }
  250.                     color: popupArea.textColor
  251.                     opacity: popupArea.textOpacity
  252.                     truncationMode: TruncationMode.Fade
  253.                     font.pixelSize: Theme.fontSizeSmall
  254.                     visible: text.length
  255.                     height: visible ? implicitHeight : 0
  256.                     textFormat: Text.PlainText
  257.                     maximumLineCount: 1
  258.                     // Only show the first line of the summary, if there is more
  259.                     text: firstLine(notificationWindow.summaryText)
  260.                 }
  261.  
  262.                 Item {
  263.                     id: bodyContainer
  264.  
  265.                     anchors {
  266.                         top: summary.bottom
  267.                         topMargin: summary.visible ? 0 : -height / 2
  268.                         left: summary.left
  269.                         right: summary.right
  270.                     }
  271.                     clip: true
  272.                     height: body.height
  273.  
  274.                     Label {
  275.                         id: body
  276.  
  277.                         width: contentWidth
  278.                         color: popupArea.textColor
  279.                         opacity: popupArea.textOpacity
  280.                         truncationMode: TruncationMode.None
  281.                         font.pixelSize: Theme.fontSizeExtraSmall
  282.                         visible: text.length
  283.                         height: visible ? implicitHeight : 0
  284.                         textFormat: Text.PlainText
  285.                         maximumLineCount: 1
  286.                         // Only show the first line of the body, if there is more
  287.                         text: firstLine(notificationWindow.bodyText)
  288.                     }
  289.                 }
  290.  
  291.                 Image {
  292.                     id: popupIcon
  293.  
  294.                     anchors {
  295.                         left: parent.left
  296.                         leftMargin: Theme.paddingMedium
  297.                         verticalCenter: parent.verticalCenter
  298.                     }
  299.                     width: Theme.iconSizeMedium
  300.                     fillMode: Image.PreserveAspectFit
  301.                     source: notificationWindow.iconUrl ? notificationWindow.iconUrl : 'image://theme/icon-lock-information'
  302.                     sourceSize.width: width
  303.  
  304.                     layer.effect: PressEffect {}
  305.                     layer.enabled: popupArea.down || popupArea.drag.active
  306.                 }
  307.  
  308.                 Image {
  309.                     id: leftIcon
  310.                     x: -(width + Theme.paddingSmall)
  311.                     anchors.verticalCenter: parent.verticalCenter
  312.                     source: (previewSettings.right_swipe_action === 1
  313.                              ? "image://theme/icon-m-acknowledge?"
  314.                              : previewSettings.right_swipe_action === 2
  315.                                ? "image://theme/icon-m-dismiss?"
  316.                                : "image://theme/icon-m-delete?") + (contentBase.x === popupArea.rightSwipeAcceptX
  317.                                                                     ? Theme.highlightColor : Theme.primaryColor)
  318.                 }
  319.  
  320.                 Image {
  321.                     id: rightIcon
  322.                     x: parent.width + Theme.paddingSmall
  323.                     anchors.verticalCenter: parent.verticalCenter
  324.                     source: (previewSettings.left_swipe_action === 1
  325.                              ? "image://theme/icon-m-acknowledge?"
  326.                              : previewSettings.left_swipe_action === 2
  327.                                ? "image://theme/icon-m-dismiss?"
  328.                                : "image://theme/icon-m-delete?") + (contentBase.x === popupArea.leftSwipeAcceptX
  329.                                                                     ? Theme.highlightColor : Theme.primaryColor)
  330.                 }
  331.  
  332.                 Image {
  333.                     id: topIcon
  334.                     y: -(height + Theme.paddingSmall)
  335.                     anchors.horizontalCenter: parent.horizontalCenter
  336.                     source: (previewSettings.down_swipe_action === 1
  337.                              ? "image://theme/icon-m-acknowledge?"
  338.                              : previewSettings.down_swipe_action === 2
  339.                                ? "image://theme/icon-m-dismiss?"
  340.                                : "image://theme/icon-m-delete?") + (contentBase.y === popupArea.downSwipeAcceptY
  341.                                                                     ? Theme.highlightColor : Theme.primaryColor)
  342.                 }
  343.  
  344.                 Behavior on x {
  345.                     id: behaviorX
  346.                     enabled: false
  347.                     NumberAnimation {duration: 300 / popupArea.drag.maximumX * Math.abs(contentBase.x); easing.type: Easing.InOutQuad}
  348.                 }
  349.  
  350.                 Behavior on y {
  351.                     id: behaviorY
  352.                     enabled: false
  353.                     NumberAnimation {duration: 300 / popupArea.drag.maximumY * contentBase.y; easing.type: Easing.InOutQuad}
  354.                 }
  355.  
  356.                 onXChanged: if (popupArea.drag.active && !popupArea.dragAxisDetermined) {
  357.                                 popupArea.drag.axis = Math.abs(x) > y ? Drag.XAxis : Drag.YAxis
  358.                                 popupArea.dragAxisDetermined = true
  359.                             }
  360.                 onYChanged: if (popupArea.drag.active && !popupArea.dragAxisDetermined) {
  361.                                 popupArea.drag.axis = y > Math.abs(x) ? Drag.YAxis : Drag.XAxis
  362.                                 popupArea.dragAxisDetermined = true
  363.                             }
  364.             }
  365.         }
  366.         property bool dragAxisDetermined: false
  367.         property var clickAction: {
  368.             previewSettings.click_action === 0 ? undefined
  369.             : previewSettings.click_action === 1
  370.               ? notificationAction
  371.               : previewSettings.click_action === 2
  372.                 ? dismissPreview
  373.                 : removeNotification
  374.         }
  375.         property int rightSwipeAcceptX: leftIcon.width + Theme.paddingMedium
  376.         property var rightSwipeAction: {
  377.             previewSettings.right_swipe_action === 0 ? undefined
  378.             : previewSettings.right_swipe_action === 1
  379.               ? notificationAction
  380.               : previewSettings.right_swipe_action === 2
  381.                 ? dismissPreview
  382.                 : removeNotification
  383.         }
  384.         property int leftSwipeAcceptX: -(rightIcon.width + Theme.paddingMedium)
  385.         property var leftSwipeAction: {
  386.             previewSettings.left_swipe_action === 0 ? undefined
  387.             : previewSettings.left_swipe_action === 1
  388.               ? notificationAction
  389.               : previewSettings.left_swipe_action === 2
  390.                 ? dismissPreview
  391.                 : removeNotification
  392.         }
  393.         property int downSwipeAcceptY: topIcon.height + Theme.paddingMedium
  394.         property var downSwipeAction: {
  395.             previewSettings.down_swipe_action === 0 ? undefined
  396.             : previewSettings.down_swipe_action === 1
  397.               ? notificationAction
  398.               : previewSettings.down_swipe_action === 2
  399.                 ? dismissPreview
  400.                 : removeNotification
  401.         }
  402.         clip: true
  403.  
  404.         drag.target: contentBase
  405.         drag.axis: Drag.XAndYAxis
  406.         drag.maximumX: rightSwipeAction !== undefined ? rightSwipeAcceptX : 0
  407.         drag.minimumX: leftSwipeAction !== undefined ? leftSwipeAcceptX : 0
  408.         drag.maximumY: downSwipeAction !== undefined ? downSwipeAcceptY : 0
  409.         drag.minimumY: 0
  410.         drag.onActiveChanged: {
  411.             if (!drag.active) {
  412.                 if (contentBase.x === rightSwipeAcceptX && rightSwipeAction !== undefined) {
  413.                     rightSwipeAction()
  414.                 }
  415.  
  416.                 if (contentBase.x === leftSwipeAcceptX && leftSwipeAction !== undefined) {
  417.                     leftSwipeAction()
  418.  
  419.                 }
  420.  
  421.                 if (contentBase.y === downSwipeAcceptY && downSwipeAction !== undefined) {
  422.                     downSwipeAction()
  423.                 }
  424.  
  425.                 behaviorX.enabled = true
  426.                 behaviorY.enabled = true
  427.                 contentBase.x = 0
  428.                 contentBase.y = 0
  429.                 drag.axis = Drag.XAndYAxis
  430.                 dragAxisDetermined = false
  431.                 console.log("Drag inactive")
  432.             }
  433.             else {
  434.                 behaviorX.enabled = false
  435.                 behaviorY.enabled = false
  436.             }
  437.         }
  438.         drag.onAxisChanged: {
  439.             if (drag.axis === Drag.XAxis) {
  440.                 contentBase.y = 0
  441.             }
  442.             else if (drag.axis === Drag.YAxis) {
  443.                 contentBase.x = 0
  444.             }
  445.         }
  446.     }
  447.  
  448.     MouseArea {
  449.         id: bannerArea
  450.  
  451.         property real contentOpacity: 0
  452.  
  453.         width: Math.max(parent.width, bannerText.x + bannerText.width + Theme.paddingMedium)
  454.         height: Lipstick.compositor.homeLayer.statusBar.height
  455.         y: -height
  456.  
  457.         onClicked: notificationWindow.notificationExpired()
  458.  
  459.         Rectangle {
  460.             anchors.fill: parent
  461.             color: Theme.overlayBackgroundColor
  462.             opacity: 0.6
  463.         }
  464.  
  465.         Image {
  466.             id: bannerIcon
  467.  
  468.             anchors {
  469.                 verticalCenter: bannerArea.verticalCenter
  470.                 left: bannerArea.left
  471.                 leftMargin: Theme.horizontalPageMargin
  472.             }
  473.             source: notificationWindow.iconUrl
  474.             sourceSize.height: height
  475.             height: Theme.iconSizeExtraSmall
  476.             fillMode: Image.PreserveAspectFit
  477.             opacity: bannerArea.contentOpacity
  478.         }
  479.  
  480.         Label {
  481.             id: bannerText
  482.  
  483.             anchors {
  484.                 verticalCenter: bannerIcon.verticalCenter
  485.                 left: bannerIcon.right
  486.                 leftMargin: Theme.paddingMedium
  487.             }
  488.             width: contentWidth
  489.             truncationMode: TruncationMode.None
  490.             font.pixelSize: Theme.fontSizeExtraSmall
  491.             // If summary text but no body, use the summary as the body
  492.             text: firstLine(notificationWindow.bodyText || notificationWindow.summaryText)
  493.             visible: text != ""
  494.             textFormat: Text.PlainText
  495.             maximumLineCount: 1
  496.             opacity: bannerArea.contentOpacity
  497.         }
  498.     }
  499.  
  500.     Loader {
  501.         id: ambiencePreviewLoader
  502.     }
  503.  
  504.     Component {
  505.         id: ambiencePreviewComponent
  506.         AmbiencePreview {
  507.             onFinished: notificationWindow.notificationComplete()
  508.         }
  509.     }
  510.  
  511.     Binding {
  512.         target: notificationFeedbackPlayer
  513.         property: "minimumPriority"
  514.         value: lipstickSettings.lockscreenVisible ? 100 : 0
  515.     }
  516.  
  517.     Timer {
  518.         id: displayTimer
  519.         interval: 0
  520.         repeat: false
  521.         onTriggered: displayNotification()
  522.     }
  523.  
  524.     Timer {
  525.         id: forceHideTimer
  526.         interval: 7000
  527.         repeat: false
  528.         onTriggered: {
  529.             notificationTimer.interval = 3000
  530.             notificationTimer.start()
  531.         }
  532.     }
  533.  
  534.     Timer {
  535.         id: notificationTimer
  536.         repeat: false
  537.         onTriggered: notificationWindow.notificationExpired()
  538.     }
  539.  
  540.     onNotificationChanged: {
  541.         if (notification) {
  542.             // Show notification only then unlocked or locked, so no notifications
  543.             // in ManagerLockout, TemporaryLockout, PermanentLockout, or Undefined
  544.             if (Desktop.deviceLockState == DeviceLock.Unlocked || Desktop.deviceLockState == DeviceLock.Locked) {
  545.                 displayTimer.restart()
  546.             } else {
  547.                 // need to acknowledge all notifications
  548.                 notificationComplete()
  549.             }
  550.         } else if (state != "") {
  551.             notificationExpired()
  552.         }
  553.     }
  554.  
  555.     function refreshPeriod() {
  556.         if (scrollAnimation.running || notificationTimer.running || forceHideTimer.running) {
  557.             forceHideTimer.stop()
  558.             scrollAnimation.reset()
  559.  
  560.             // If the notification is already showing, restart the display period with a shorter timeout
  561.             notificationShown(notificationTimer.running ? 3000 : 5000)
  562.         }
  563.     }
  564.  
  565.     onSummaryTextChanged: refreshPeriod()
  566.     onBodyTextChanged: refreshPeriod()
  567.     onIconUrlChanged: refreshPeriod()
  568.  
  569.     function displayNotification() {
  570.         // We use two different presentation styles: one that can be clicked and one that cannot.
  571.         // Check for configurations that can't be correctly activated
  572.         if (notification.remoteActions.length == 0) {
  573.             if (notification.previewSummary && notification.previewBody) {
  574.                 // Notifications with preview summary + preview body should have actions, as tapping on the preview pop-up should trigger some action
  575.                 console.log('Warning: Notification has both preview summary and preview body but no actions. Remove the preview body or add an action:', notification.appName, notification.category, notification.previewSummary, notification.previewBody)
  576.             }
  577.         } else {
  578.             if (notification.previewSummary && !notification.previewBody) {
  579.                 // Notifications with preview summary but no body should not have any actions, as the small preview banner is too small to receive presses
  580.                 console.log('Warning: Notification has an action but only shows a preview summary. Add a preview body or remove the actions:', notification.appName, notification.category, notification.previewSummary, notification.previewBody)
  581.             } else if ((!notification.previewSummary && !notification.previewBody) && notification.hints['transient'] == true) {
  582.                 console.log('Warning: Notification has actions but is transient and without a preview, its actions will not be triggerable from the UI:', notification.appName, notification.category, notification.previewSummary, notification.previewBody)
  583.             }
  584.         }
  585.  
  586.         if (showNotification) {
  587.             if (notification.category === "x-jolla.ambience.preview") {
  588.                 ambiencePreviewLoader.sourceComponent = ambiencePreviewComponent
  589.                 var preview = ambiencePreviewLoader.item
  590.                 if (preview) {
  591.                     preview.displayName = notification.previewSummary
  592.                     preview.coverImage = notification.previewBody
  593.                     preview.show()
  594.                     state = "showAmbience"
  595.                 }
  596.             } else {
  597.                 // Show preview banner or pop-up
  598.                 var hasActions = notification.remoteActions.length > 0
  599.                 var hasMultipleLines = (notification.previewSummary.length > 0 && notification.previewBody.length > 0)
  600.                 state = hasActions || hasMultipleLines ? "showPopup" : "showBanner"
  601.             }
  602.         }
  603.     }
  604.  
  605.     function notificationShown(timeout) {
  606.         // Min 1sec and max 5secs
  607.         if (!timeout && notification.expireTimeout > 0) {
  608.             timeout = Math.min(Math.max(notification.expireTimeout, 1000), 5000)
  609.         } else {
  610.             timeout = previewSettings.timeout
  611.         }
  612.  
  613.         var scroll = false
  614.         if (state == "showPopup") {
  615.             scroll = scrollAnimation.initialize(body, bodyContainer)
  616.             popupArea.notificationShownNSteady = true
  617.         } else if (state == "showBanner") {
  618.             scroll = scrollAnimation.initialize(bannerArea, notificationWindow)
  619.         }
  620.  
  621.         if (scroll) {
  622.             scrollAnimation.start()
  623.             forceHideTimer.start()
  624.         } else {
  625.             notificationTimer.interval = timeout
  626.             notificationTimer.restart()
  627.         }
  628.     }
  629.  
  630.     function notificationExpired() {
  631.         forceHideTimer.stop()
  632.         notificationTimer.stop()
  633.  
  634.         if (state == "showPopup") {
  635.             state = "hidePopup"
  636.         } else if (state == "showBanner") {
  637.             state = "hideBanner"
  638.         } else {
  639.             notificationComplete()
  640.         }
  641.     }
  642.  
  643.     function notificationComplete() {
  644.         state = ""
  645.         _invoked = false
  646.         notificationPreviewPresenter.showNextNotification()
  647.     }
  648.  
  649.     states: [
  650.         State {
  651.             name: "showPopup"
  652.             PropertyChanges {
  653.                 target: notificationWindow
  654.                 opacity: 1
  655.                 visible: true
  656.             }
  657.             PropertyChanges {
  658.                 target: popupArea
  659.                 opacity: 1
  660.                 textOpacity: 1
  661.             }
  662.             PropertyChanges {
  663.                 target: body
  664.                 x: 0
  665.             }
  666.         },
  667.         State {
  668.             name: "hidePopup"
  669.             PropertyChanges {
  670.                 target: notificationWindow
  671.                 opacity: 1
  672.                 visible: true
  673.             }
  674.             PropertyChanges {
  675.                 target: body
  676.                 // Keep the body at whatever scroll position it is currently in
  677.                 x: body.x
  678.             }
  679.         },
  680.         State {
  681.             name: "showBanner"
  682.             PropertyChanges {
  683.                 target: notificationWindow
  684.                 opacity: 1
  685.                 visible: true
  686.             }
  687.             PropertyChanges {
  688.                 target: bannerArea
  689.                 y: 0
  690.                 x: 0
  691.                 contentOpacity: 1
  692.             }
  693.         },
  694.         State {
  695.             name: "hideBanner"
  696.             PropertyChanges {
  697.                 target: notificationWindow
  698.                 opacity: 1
  699.                 visible: true
  700.             }
  701.             PropertyChanges {
  702.                 target: bannerArea
  703.                 // Keep the text at whatever scroll position it is currently in
  704.                 x: bannerArea.x
  705.                 contentOpacity: 1
  706.             }
  707.         },
  708.         State {
  709.             name: "showAmbience"
  710.             PropertyChanges {
  711.                 target: notificationWindow
  712.                 opacity: 1
  713.                 visible: true
  714.             }
  715.         }
  716.     ]
  717.  
  718.     transitions: [
  719.         Transition {
  720.             to: "showPopup"
  721.             SequentialAnimation {
  722.                 ParallelAnimation {
  723.                     NumberAnimation {
  724.                         target: popupArea
  725.                         property: "width"
  726.                         duration: 200
  727.                         from: popupArea.displayWidth * 0.9
  728.                         to: popupArea.displayWidth
  729.                         easing.type: Easing.OutQuad
  730.                     }
  731.                     SequentialAnimation {
  732.                         NumberAnimation {
  733.                             target: popupArea
  734.                             property: "opacity"
  735.                             duration: 50
  736.                         }
  737.                         NumberAnimation {
  738.                             target: popupArea
  739.                             property: "textOpacity"
  740.                             duration: 150
  741.                         }
  742.                     }
  743.                 }
  744.                 ScriptAction {
  745.                     script: notificationWindow.notificationShown()
  746.                 }
  747.             }
  748.         },
  749.         Transition {
  750.             to: "hidePopup"
  751.             SequentialAnimation {
  752.                 ScriptAction {script: popupArea.notificationShownNSteady = false}
  753.                 ParallelAnimation {
  754.                     SequentialAnimation {
  755.                         NumberAnimation {
  756.                             target: popupArea
  757.                             property: "textOpacity"
  758.                             duration: 150
  759.                         }
  760.                         NumberAnimation {
  761.                             target: popupArea
  762.                             property: "opacity"
  763.                             duration: 50
  764.                         }
  765.                     }
  766.                     NumberAnimation {
  767.                         target: popupArea
  768.                         property: "width"
  769.                         duration: 200
  770.                         from: popupArea.displayWidth
  771.                         to: popupArea.displayWidth * 0.9
  772.                         easing.type: Easing.InQuad
  773.                     }
  774.                 }
  775.                 NumberAnimation {
  776.                     target: popupIcon
  777.                     property: "x"
  778.                     duration: 150
  779.                     easing.type: Easing.InQuad
  780.                 }
  781.                 ScriptAction {
  782.                     script: {
  783.                         if (removeRequested) {
  784.                             notification.removeRequested()
  785.                             removeRequested = false
  786.                         }
  787.                         notificationWindow.notificationComplete()
  788.                     }
  789.                 }
  790.             }
  791.         },
  792.         Transition {
  793.             to: "showBanner"
  794.             SequentialAnimation {
  795.                 ParallelAnimation {
  796.                     PropertyAnimation {
  797.                         target: bannerArea
  798.                         property: "y"
  799.                         duration: 200
  800.                         easing.type: Easing.OutQuad
  801.                     }
  802.                     SequentialAnimation {
  803.                         PauseAnimation { duration: 150 }
  804.                         PropertyAnimation {
  805.                             target: bannerArea
  806.                             property: "contentOpacity"
  807.                             duration: 150
  808.                         }
  809.                     }
  810.                 }
  811.                 ScriptAction {
  812.                     script: {
  813.                         notificationWindow.notificationShown()
  814.                     }
  815.                 }
  816.             }
  817.         },
  818.         Transition {
  819.             to: "hideBanner"
  820.             SequentialAnimation {
  821.                 PropertyAnimation {
  822.                     target: bannerArea
  823.                     property: "y"
  824.                     duration: 200
  825.                     easing.type: Easing.OutQuad
  826.                 }
  827.                 ScriptAction {
  828.                     script: notificationWindow.notificationComplete()
  829.                 }
  830.             }
  831.         }
  832.     ]
  833.  
  834.     SequentialAnimation {
  835.         id: scrollAnimation
  836.  
  837.         function initialize(targetItem, containerItem) {
  838.             target = targetItem
  839.             container = containerItem
  840.             return range > 0
  841.         }
  842.  
  843.         function reset() {
  844.             stop()
  845.             if (target) {
  846.                 target.x = 0
  847.                 target = null
  848.             }
  849.         }
  850.  
  851.         property Item target
  852.         property Item container
  853.         property real range: target && container ? target.width - container.width : 0
  854.         property real speed: 120
  855.         property real accelerationDuration: 500
  856.  
  857.         PauseAnimation { duration: 2000 }
  858.         PropertyAnimation {
  859.             id: startScrollingAnimation
  860.  
  861.             target: scrollAnimation.target
  862.             property: "x"
  863.             from: 0
  864.             to: Math.max(-scrollAnimation.range / 2, -scrollAnimation.speed * scrollAnimation.accelerationDuration / 1000 / 2)
  865.             duration: (to - from) < 0 ? scrollAnimation.accelerationDuration : 0
  866.             easing.type: Easing.InQuad
  867.         }
  868.         PropertyAnimation {
  869.             property real animationDuration: -(to - from) * 1000 / scrollAnimation.speed
  870.  
  871.             target: scrollAnimation.target
  872.             property: "x"
  873.             from: startScrollingAnimation.to
  874.             to: stopScrollingAnimation.from
  875.             duration: Math.max(animationDuration, 0)
  876.             easing.type: Easing.Linear
  877.         }
  878.         PropertyAnimation {
  879.             id: stopScrollingAnimation
  880.  
  881.             target: scrollAnimation.target
  882.             property: "x"
  883.             from: Math.min(-scrollAnimation.range / 2, -scrollAnimation.range + scrollAnimation.speed * scrollAnimation.accelerationDuration / 1000 / 2)
  884.             to: -scrollAnimation.range
  885.             duration: (to - from) < 0 ? scrollAnimation.accelerationDuration : 0
  886.             easing.type: Easing.OutQuad
  887.         }
  888.         ScriptAction {
  889.             script: {
  890.                 scrollAnimation.target = null
  891.                 notificationTimer.interval = 2000
  892.                 notificationTimer.start()
  893.             }
  894.         }
  895.     }
  896. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement