1
0
Fork 0
mirror of https://github.com/HenkKalkwater/harbour-sailfin.git synced 2025-09-04 01:42:44 +00:00

WIP: implement search

This commit is contained in:
Chris Josten 2021-01-17 17:08:07 +01:00
parent 79d378c9ed
commit eac8faf173
9 changed files with 356 additions and 77 deletions

View file

@ -23,6 +23,7 @@ set(sailfin_QML_SOURCES
qml/components/music/NarrowAlbumCover.qml
qml/components/music/WideAlbumCover.qml
qml/components/music/SongDelegate.qml
qml/components/search/SearchResults.qml
qml/components/videoplayer/VideoError.qml
qml/components/videoplayer/VideoHud.qml
qml/components/GlassyBackground.qml
@ -62,7 +63,7 @@ set(sailfin_QML_SOURCES
add_executable(harbour-sailfin ${harbour-sailfin_SOURCES} ${sailfin_QML_SOURCES})
target_link_libraries(harbour-sailfin PRIVATE Qt5::Gui Qt5::Qml Qt5::Quick SailfishApp::SailfishApp
# Note: this may break when the compiler changes. -rdynamic and -pie seem to be needed for the
# invoker/booster to work
# invoker/booster to work
jellyfin-qt "-Wl,-rpath,${CMAKE_INSTALL_LIBDIR} -rdynamic -pie")
install(TARGETS harbour-sailfin

View file

@ -30,6 +30,7 @@ SilicaItem {
property string fallbackImage
property bool usingFallbackImage
property color fallbackColor: Theme.highlightColor
property bool hideFallbackColor: false
property var __parentPage : null
property bool alreadyLoaded: false
@ -56,7 +57,7 @@ SilicaItem {
anchors.fill: parent
asynchronous: true
fillMode: root.fillMode
opacity: 1
opacity: hideFallbackColor ? 0.0 : 1.0
source: alreadyLoaded || [PageStatus.Active, PageStatus.Deactivating].indexOf(__parentPage.status) >= 0 ? root.source : ""
onStatusChanged: {
if (status == Image.Ready) {
@ -73,6 +74,7 @@ SilicaItem {
GradientStop { position: 1.0; color: Theme.highlightDimmerFromColor(fallbackColor, Theme.colorScheme); }
}
opacity: 0
visible: !hideFallbackColor
}
Image {
@ -132,7 +134,7 @@ SilicaItem {
when: realImage.status === Image.Ready
PropertyChanges {
target: realImage
//opacity: 1
opacity: 1
}
}
]

View file

@ -0,0 +1,40 @@
import QtQuick 2.6
import Sailfish.Silica 1.0
import nl.netsoj.chris.Jellyfin 1.0
SilicaListView {
id: root
model: query.length ? searchModel : 0
property alias query: searchModel.searchTerm
delegate: ListItem {
width: parent.width
height: Theme.itemSizeLarge
Label {
anchors.centerIn: parent
width: parent.width
text: model.name
}
}
add: Transition {
NumberAnimation { property: "scale"; from: 0.0001; to: 1.0; }
FadeAnimation { from: 0.0; to: 1.0; }
}
move: Transition {
NumberAnimation {
properties: "x,y"
}
}
remove: Transition {
NumberAnimation { property: "scale"; from: 1.0; to: 0.0001; }
FadeAnimation { from: 1.0; to: 0.0; }
}
SearchModel {
id: searchModel
apiClient: ApiClient
recursive: true
}
}

View file

@ -22,6 +22,7 @@ import Sailfish.Silica 1.0
import nl.netsoj.chris.Jellyfin 1.0
import "../components"
import "../components/search"
import "../"
import "../Utils.js" as Utils
@ -36,6 +37,7 @@ Page {
allowedOrientations: Orientation.All
SilicaFlickable {
id: mainView
anchors.fill: parent
// PullDownMenu and PushUpMenu must be declared in SilicaFlickable, SilicaListView or SilicaGridView
@ -66,73 +68,92 @@ Page {
id: mediaLibraryModel2
apiClient: ApiClient
}
Item {
id: searchBoxPlaceholder
width: parent.width
height: searchBox.height
MoreSection {
text: qsTr("Resume watching")
clickable: false
busy: userResumeModel.status == ApiModel.Loading
Loader {
SearchField {
id: searchBox
width: parent.width
sourceComponent: carrouselView
property alias itemModel: userResumeModel
property string collectionType: "series"
UserItemResumeModel {
id: userResumeModel
apiClient: ApiClient
limit: 12
recursive: true
}
}
}
MoreSection {
text: qsTr("Next up")
clickable: false
busy: showNextUpModel.status == ApiModel.Loading
Loader {
width: parent.width
sourceComponent: carrouselView
property alias itemModel: showNextUpModel
property string collectionType: "series"
ShowNextUpModel {
id: showNextUpModel
apiClient: ApiClient
limit: 12
}
placeholderText: qsTr("Search")
}
}
UserViewModel {
id: mediaLibraryModel
apiClient: ApiClient
Label {
text: "%1 results".arg(searchView.count)
}
Repeater {
model: mediaLibraryModel
Column {
id: homeView
width: parent.width
MoreSection {
text: model.name
busy: userItemModel.status != ApiModel.Ready
onHeaderClicked: pageStack.push(Qt.resolvedUrl("itemdetails/CollectionPage.qml"), {"itemId": model.id})
text: qsTr("Resume watching")
clickable: false
busy: userResumeModel.status == ApiModel.Loading
Loader {
width: parent.width
sourceComponent: carrouselView
property alias itemModel: userItemModel
property string collectionType: model.collectionType || ""
property alias itemModel: userResumeModel
property string collectionType: "series"
UserItemLatestModel {
id: userItemModel
UserItemResumeModel {
id: userResumeModel
apiClient: ApiClient
limit: 12
recursive: true
}
}
}
MoreSection {
text: qsTr("Next up")
clickable: false
busy: showNextUpModel.status == ApiModel.Loading
Loader {
width: parent.width
sourceComponent: carrouselView
property alias itemModel: showNextUpModel
property string collectionType: "series"
ShowNextUpModel {
id: showNextUpModel
apiClient: ApiClient
parentId: model.id
limit: 12
}
Connections {
target: mediaLibraryModel
onStatusChanged: {
console.log("MediaLibraryModel status " + status)
if (status == ApiModel.Ready) {
userItemModel.reload()
}
}
UserViewModel {
id: mediaLibraryModel
apiClient: ApiClient
}
Repeater {
model: mediaLibraryModel
MoreSection {
text: model.name
busy: userItemModel.status != ApiModel.Ready
onHeaderClicked: pageStack.push(Qt.resolvedUrl("itemdetails/CollectionPage.qml"), {"itemId": model.id})
Loader {
width: parent.width
sourceComponent: carrouselView
property alias itemModel: userItemModel
property string collectionType: model.collectionType || ""
UserItemLatestModel {
id: userItemModel
apiClient: ApiClient
parentId: model.id
limit: 12
}
Connections {
target: mediaLibraryModel
onStatusChanged: {
console.log("MediaLibraryModel status " + status)
if (status == ApiModel.Ready) {
userItemModel.reload()
}
}
}
}
@ -167,6 +188,42 @@ Page {
}
}
SearchResults {
id: searchView
anchors.fill: parent
header: Item {
width: parent.width
height: searchBox.height
}
query: searchBox.text
visible: false
opacity: 0
}
states: [
State {
name: "search"
when: searchBox.text.length
PropertyChanges {
target: searchView
visible: true
opacity: 1
}
PropertyChanges {
target: mainView
opacity: 0
visible: false
}
ParentChange {
target: searchBox
parent: searchView.headerItem
}
StateChangeScript {
script: searchBox.forceActiveFocus()
}
}
]
onStatusChanged: {
if (status == PageStatus.Active) {
appWindow.itemData = null
@ -181,7 +238,7 @@ Page {
/**
* Loads models if not laoded. Set force to true to reload models
* Loads models if not loaded. Set force to true to reload models
* even if loaded.
*/
function loadModels(force) {

View file

@ -68,6 +68,7 @@ Page {
top: parent.top
bottom: parent.bottom
}
hideFallbackColor: true
source: ApiClient.baseUrl + "/Users/" + ApiClient.userId + "/Images/Primary?tag=" + loggedInUser.primaryImageTag
}