diff --git a/app/qml/BooksBookView.qml b/app/qml/BooksBookView.qml index f9f78bd..a5fc89d 100644 --- a/app/qml/BooksBookView.qml +++ b/app/qml/BooksBookView.qml @@ -65,6 +65,7 @@ Item { property alias viewInteractive: bookView.interactive property alias pullDownMenu: menu + property alias isCurrentView: menu.visible property bool pageActive readonly property bool viewActive: pageActive && Qt.application.active && book @@ -131,11 +132,24 @@ Item { ThemeEffect { effect: ThemeEffect.Press } } + Behavior on opacity { + enabled: menu.backToLibrary === 0 + FadeAnimation { } + } + + Binding on opacity { + // Fade out the page while menu is bouncing back + when: menu.backToLibrary < 0 + value: menu.flickable.contentY / menu.backToLibrary + } + PullDownMenu { id: menu visible: false // BooksMainPage will make it visible when it's needed + property real backToLibrary + MenuItem { //: Pulley menu item //% "Settings" @@ -159,7 +173,16 @@ Item { //% "Back to library" text: qsTrId("harbour-books-book-view-back") - onClicked: root.closeBook() + // Delay the actual action until bounce back is finished + onClicked: menu.backToLibrary = flickable.contentY + } + + onActiveChanged: { + if (!active && backToLibrary < 0) { + // The actual "Back to library" action + backToLibrary = 0 + root.closeBook() + } } } @@ -200,7 +223,7 @@ Item { orientation: ListView.Horizontal snapMode: ListView.SnapOneItem preferredHighlightBegin: 0 - preferredHighlightEnd: width + preferredHighlightEnd: width + spacing highlightRangeMode: ListView.StrictlyEnforceRange spacing: Theme.paddingMedium opacity: loading ? 0 : 1 diff --git a/app/qml/BooksMainPage.qml b/app/qml/BooksMainPage.qml index 85d9603..6634dd4 100644 --- a/app/qml/BooksMainPage.qml +++ b/app/qml/BooksMainPage.qml @@ -36,7 +36,7 @@ import Sailfish.Silica 1.0 import harbour.books 1.0 Page { - id: root + id: page allowedOrientations: window.allowedOrientations @@ -45,28 +45,21 @@ Page { readonly property Item currentView: Settings.currentBook ? bookView : storageView property Item bookView + readonly property real fadeInThreshold: height/4 + readonly property real swipeAwayThreshold: 3 * height/4 + Component.onCompleted: createBookViewIfNeeded() - onCurrentViewChanged: updatePullDownMenu() + onCurrentViewChanged: { + if (currentView) { + flickable.pullDownMenu = currentView.pullDownMenu + flickable.pullDownMenu.flickable = flickable + } + } function createBookViewIfNeeded() { if (Settings.currentBook && !bookView) { bookView = bookViewComponent.createObject(flickable.contentItem) - updatePullDownMenu() - } - } - - function updatePullDownMenu() { - var menu = currentView ? currentView.pullDownMenu : null - if (menu) { - menu.visible = true - } - if (flickable.pullDownMenu !== menu) { - var prevMenu = flickable.pullDownMenu - flickable.pullDownMenu = menu - if (prevMenu) { - prevMenu.visible = false - } } } @@ -75,26 +68,44 @@ Page { onCurrentBookChanged: createBookViewIfNeeded() } - Connections { - target: currentView - onPullDownMenuChanged: updatePullDownMenu() - } - SilicaFlickable { id: flickable anchors.fill: parent + contentWidth: page.width + contentHeight: Settings.currentBook ? (2 * page.height) : page.height flickableDirection: Flickable.VerticalFlick - interactive: currentView && currentView.viewInteractive + flickDeceleration: maximumFlickVelocity + interactive: currentView && currentView.viewInteractive && !swipeAwayAnimation.running + pressDelay: 0 BooksStorageView { id: storageView - anchors.fill: parent - pageActive: root.pageActive - opacity: Settings.currentBook ? 0 : 1 + + width: page.width + height: page.height + y: Settings.currentBook ? flickable.contentY : 0 + pageActive: page.pageActive + isCurrentView: currentView === storageView + opacity: Settings.currentBook ? ((y > fadeInThreshold) ? 1 : (y > 0) ? y/fadeInThreshold : 0) : 1 visible: opacity > 0 - Behavior on opacity { FadeAnimation {} } + onOpenBook: Settings.currentBook = book + + Behavior on opacity { + enabled: !Settings.currentBook + FadeAnimation { } + } + } + + onMovementEnded: { + if (contentY > 0 && Settings.currentBook) { + if (contentY > swipeAwayThreshold) { + swipeAwayAnimation.start() + } else { + unswipeAnimation.start() + } + } } } @@ -102,14 +113,51 @@ Page { id: bookViewComponent BooksBookView { - anchors.fill: parent - opacity: Settings.currentBook ? 1 : 0 - visible: opacity > 0 - orientation: root.orientation - pageActive: root.pageActive + id: bookView + + width: page.width + height: page.height + z: storageView.z + 1 + visible: !!Settings.currentBook + orientation: page.orientation + isCurrentView: currentView === bookView + pageActive: page.pageActive book: Settings.currentBook ? Settings.currentBook : null + onCloseBook: Settings.currentBook = null - Behavior on opacity { FadeAnimation {} } + onVisibleChanged: if (visible) opacity = 1 + } + } + + SequentialAnimation { + id: swipeAwayAnimation + + alwaysRunToEnd: true + NumberAnimation { + target: flickable + property: "contentY" + to: page.height + duration: 150 + easing.type: Easing.InQuad + } + ScriptAction { + script: { + Settings.currentBook = null + flickable.contentY = 0 + } + } + } + + SequentialAnimation { + id: unswipeAnimation + + alwaysRunToEnd: true + NumberAnimation { + target: flickable + property: "contentY" + to: 0 + duration: 150 + easing.type: Easing.InOutQuad } } } diff --git a/app/qml/BooksStorageView.qml b/app/qml/BooksStorageView.qml index d1ec6d3..10fd852 100644 --- a/app/qml/BooksStorageView.qml +++ b/app/qml/BooksStorageView.qml @@ -40,6 +40,7 @@ Item { property alias viewInteractive: storageList.interactive property alias pullDownMenu: menu + property alias isCurrentView: menu.visible property bool pageActive property bool editMode: false @@ -96,8 +97,6 @@ Item { PullDownMenu { id: menu - visible: false // BooksMainPage will make it visible when it's needed - MenuItem { //: Pulley menu item //% "Settings" @@ -187,6 +186,8 @@ Item { flickDeceleration: maximumFlickVelocity orientation: ListView.Horizontal snapMode: ListView.SnapOneItem + preferredHighlightBegin: 0 + preferredHighlightEnd: width + spacing highlightRangeMode: ListView.StrictlyEnforceRange spacing: Theme.paddingMedium interactive: !dragInProgress && !dragScrollAnimation.running