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:
parent
79d378c9ed
commit
eac8faf173
9 changed files with 356 additions and 77 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
40
sailfish/qml/components/search/SearchResults.qml
Normal file
40
sailfish/qml/components/search/SearchResults.qml
Normal 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
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -68,6 +68,7 @@ Page {
|
|||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
}
|
||||
hideFallbackColor: true
|
||||
source: ApiClient.baseUrl + "/Users/" + ApiClient.userId + "/Images/Primary?tag=" + loggedInUser.primaryImageTag
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue