ui-improvements
- open profile picture - improved media viewer - improved user suggestion - better responsive UI design - code refactoring - updated settings page
This commit is contained in:
parent
fd2f317f25
commit
16e211ddb9
23 changed files with 525 additions and 370 deletions
|
@ -57,6 +57,8 @@ DISTFILES += qml/harbour-tooter.qml \
|
|||
qml/pages/ProfilePage.qml \
|
||||
qml/pages/SettingsPage.qml \
|
||||
qml/pages/components/InfoBanner.qml \
|
||||
qml/pages/components/MediaFullScreen.qml \
|
||||
qml/pages/components/ProfileImage.qml \
|
||||
qml/pages/components/VisualContainer.qml \
|
||||
qml/pages/components/MiniStatus.qml \
|
||||
qml/pages/components/MiniHeader.qml \
|
||||
|
@ -66,7 +68,6 @@ DISTFILES += qml/harbour-tooter.qml \
|
|||
qml/pages/components/ProfileHeader.qml \
|
||||
qml/pages/components/MediaBlock.qml \
|
||||
qml/pages/components/MyImage.qml \
|
||||
qml/pages/components/ImageFullScreen.qml \
|
||||
qml/cover/CoverPage.qml \
|
||||
qml/pages/MainPage.qml \
|
||||
qml/pages/LoginPage.qml \
|
||||
|
|
|
@ -57,7 +57,6 @@ CoverBackground {
|
|||
horizontalAlignment: Image.AlignLeft
|
||||
verticalAlignment: Image.AlignBottom
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
source: "../images/tooter.svg"
|
||||
}
|
||||
Timer {
|
||||
|
@ -78,6 +77,7 @@ CoverBackground {
|
|||
}
|
||||
source: "image://theme/icon-s-alarm?" + Theme.highlightColor
|
||||
}
|
||||
|
||||
Label {
|
||||
id: notificationsLbl
|
||||
anchors {
|
||||
|
@ -112,8 +112,11 @@ CoverBackground {
|
|||
CoverAction {
|
||||
iconSource: "image://theme/icon-cover-new"
|
||||
onTriggered: {
|
||||
pageStack.push(Qt.resolvedUrl("./../pages/Conversation.qml"), {})
|
||||
appWindow.activate();
|
||||
pageStack.push(Qt.resolvedUrl("./../pages/ConversationPage.qml"), {
|
||||
headerTitle: qsTr("New Toot"),
|
||||
type: "new"
|
||||
})
|
||||
appWindow.activate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ ApplicationWindow {
|
|||
Logic.conf['notificationLastID'] = 0
|
||||
|
||||
if (Logic.conf['instance']) {
|
||||
Logic.api = new Logic.MastodonAPI({
|
||||
Logic.api = Logic.mastodonAPI({
|
||||
"instance": Logic.conf['instance'],
|
||||
"api_user_token": ""
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// do whatever you want with it
|
||||
// but please don't hurt it (and keep this header)
|
||||
|
||||
var MastodonAPI = function(config) {
|
||||
var mastodonAPI = function(config) {
|
||||
var apiBase = config.instance + "/api/v1/";
|
||||
return {
|
||||
setConfig: function (key, value) {
|
||||
|
@ -236,7 +236,7 @@ var MastodonAPI = function(config) {
|
|||
};
|
||||
|
||||
// node.js
|
||||
if (typeof module !== 'undefined') { module.exports = MastodonAPI; };
|
||||
if (typeof module !== 'undefined') { module.exports = mastodonAPI; };
|
||||
|
||||
String.prototype.replaceAll = function(search, replacement) {
|
||||
var target = this;
|
||||
|
|
|
@ -22,7 +22,7 @@ WorkerScript.onMessage = function(msg) {
|
|||
if (typeof msg.conf['loadImages'] !== "undefined")
|
||||
loadImages = msg.conf['loadImages']
|
||||
|
||||
var API = MastodonAPI({ instance: msg.conf.instance, api_user_token: msg.conf.api_user_token});
|
||||
var API = mastodonAPI({ instance: msg.conf.instance, api_user_token: msg.conf.api_user_token});
|
||||
if (msg.method === "POST"){
|
||||
API.post(msg.action, msg.params, function(data) {
|
||||
if (msg.bgAction){
|
||||
|
@ -298,13 +298,13 @@ function addEmojis(item, data){
|
|||
var emoji, i;
|
||||
for (i = 0; i < data["emojis"].length; i++){
|
||||
emoji = data["emojis"][i];
|
||||
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"middle\" width=\"24\" height=\"24\">")
|
||||
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"top\" width=\"50\" height=\"50\">")
|
||||
//console.log(JSON.stringify(data["emojis"][i]))
|
||||
}
|
||||
if (data["reblog"])
|
||||
for (i = 0; i < data["reblog"]["emojis"].length; i++){
|
||||
emoji = data["reblog"]["emojis"][i];
|
||||
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"middle\" width=\"24\" height=\"24\">")
|
||||
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"top\" width=\"50\" height=\"50\">")
|
||||
}
|
||||
|
||||
return item;
|
||||
|
|
|
@ -43,10 +43,6 @@ Page {
|
|||
}
|
||||
}
|
||||
|
||||
InfoBanner {
|
||||
id: sentBanner
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: mediaModel
|
||||
onCountChanged: {
|
||||
|
@ -73,11 +69,13 @@ Page {
|
|||
title: headerTitle // pageTitle pushed from MainPage.qml or VisualContainer.qml
|
||||
}
|
||||
clip: true
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: panel.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: if (panel.open == true) {
|
||||
panel.top
|
||||
} else {
|
||||
hiddenPanel.top
|
||||
}
|
||||
model: mdl
|
||||
section {
|
||||
|
@ -100,12 +98,7 @@ Page {
|
|||
}
|
||||
|
||||
PullDownMenu {
|
||||
visible: type == "reply" && toot_url != ""
|
||||
/* MenuItem {
|
||||
text: qsTr("Open in Browser")
|
||||
onClicked: Qt.openUrlExternally(toot_url);
|
||||
} */
|
||||
// ! url isn't always fetched. Needs a solution.
|
||||
visible: type === "reply" && toot_url !== ""
|
||||
MenuItem {
|
||||
text: qsTr("Copy Link to Clipboard")
|
||||
onClicked: Clipboard.text = toot_url;
|
||||
|
@ -121,16 +114,17 @@ Page {
|
|||
anchors.right: panel.right
|
||||
anchors.top: parent.top
|
||||
height: implicitHeight
|
||||
//height: suggestedModel.count > 6 ? Theme.itemSizeMedium * 6 : Theme.itemSizeMedium * suggestedModel.count
|
||||
color: Theme.highlightDimmerColor
|
||||
|
||||
SilicaListView {
|
||||
rotation: 180
|
||||
anchors.fill: parent
|
||||
model: suggestedModel
|
||||
clip: true
|
||||
quickScroll: false
|
||||
VerticalScrollDecorator {}
|
||||
delegate: ItemUser {
|
||||
rotation: 180
|
||||
onClicked: {
|
||||
var start = toot.cursorPosition
|
||||
while (toot.text[start] !== "@" && start > 0) {
|
||||
|
@ -149,24 +143,20 @@ Page {
|
|||
}
|
||||
}
|
||||
onCountChanged: {
|
||||
positionViewAtIndex(suggestedModel.count - 1, ListView.End)
|
||||
positionViewAtBeginning(suggestedModel.count - 1, ListView.Beginning)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DockedPanel {
|
||||
id: panel
|
||||
open: true
|
||||
//onExpandedChanged: {
|
||||
// if (!expanded) {
|
||||
// show()
|
||||
// }
|
||||
//}
|
||||
width: parent.width
|
||||
height: progressBar.height + toot.height + (mediaModel.count ? uploadedImages.height : 0)
|
||||
+ btnContentWarning.height + Theme.paddingMedium
|
||||
+ (warningContent.visible ? warningContent.height : 0)
|
||||
dock: Dock.Bottom
|
||||
open: true
|
||||
animationDuration: 200
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
|
@ -260,8 +250,12 @@ Page {
|
|||
IconButton {
|
||||
id: btnSmileys
|
||||
property string selection
|
||||
onSelectionChanged: {
|
||||
console.log(selection)
|
||||
opacity: 0.7
|
||||
icon {
|
||||
color: Theme.highlightColor
|
||||
width: Theme.iconSizeSmallPlus
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "../../qml/images/emojiselect.svg"
|
||||
}
|
||||
anchors {
|
||||
top: warningContent.bottom
|
||||
|
@ -269,8 +263,9 @@ Page {
|
|||
right: parent.right
|
||||
rightMargin: Theme.paddingSmall
|
||||
}
|
||||
opacity: 0.6
|
||||
icon.source: "../../qml/images/emojiselect.svg"
|
||||
onSelectionChanged: {
|
||||
console.log(selection)
|
||||
}
|
||||
onClicked: pageStack.push(emojiSelect)
|
||||
}
|
||||
|
||||
|
@ -501,12 +496,12 @@ Page {
|
|||
}
|
||||
|
||||
BackgroundItem {
|
||||
id: showPanel
|
||||
id: hiddenPanel
|
||||
visible: !panel.open
|
||||
height: Theme.paddingMedium
|
||||
height: Theme.paddingLarge * 0.5
|
||||
width: parent.width
|
||||
opacity: enabled ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimator {} }
|
||||
opacity: enabled ? 0.6 : 0.0
|
||||
Behavior on opacity { FadeAnimator { duration: 400 } }
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
|
@ -518,8 +513,18 @@ Page {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
id: hiddenPanelBackground
|
||||
width: parent.width
|
||||
height: progressBarShowPanel.height
|
||||
height: parent.height
|
||||
color: Theme.highlightBackgroundColor
|
||||
opacity: 0.4
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: progressBarBackground
|
||||
width: parent.width
|
||||
height: progressBarHiddenPanel.height
|
||||
color: Theme.highlightBackgroundColor
|
||||
opacity: 0.2
|
||||
anchors {
|
||||
|
@ -530,19 +535,7 @@ Page {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
color: Theme.highlightBackgroundColor
|
||||
opacity: 0.2
|
||||
height: showPanel.height
|
||||
width: showPanel.width
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: progressBarShowPanel
|
||||
id: progressBarHiddenPanel
|
||||
width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0
|
||||
height: Theme.itemSizeSmall * 0.05
|
||||
color: Theme.highlightBackgroundColor
|
||||
|
@ -559,4 +552,8 @@ Page {
|
|||
id: emojiSelect
|
||||
}
|
||||
|
||||
InfoBanner {
|
||||
id: sentBanner
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import "./components/"
|
|||
|
||||
Page {
|
||||
id: mainPage
|
||||
|
||||
property bool isFirstPage: true
|
||||
property bool isTablet: true //Screen.sizeCategory >= Screen.Large
|
||||
|
||||
|
@ -39,6 +40,7 @@ Page {
|
|||
height: parent.itemHeight
|
||||
onOpenDrawer: infoPanel.open = setDrawer
|
||||
}
|
||||
|
||||
MyList{
|
||||
id: tlNotifications;
|
||||
title: qsTr("Notifications")
|
||||
|
@ -49,6 +51,7 @@ Page {
|
|||
height: parent.itemHeight
|
||||
onOpenDrawer: infoPanel.open = setDrawer
|
||||
}
|
||||
|
||||
MyList{
|
||||
id: tlLocal;
|
||||
title: qsTr("Local")
|
||||
|
@ -59,6 +62,7 @@ Page {
|
|||
height: parent.itemHeight
|
||||
onOpenDrawer: infoPanel.open = setDrawer
|
||||
}
|
||||
|
||||
MyList{
|
||||
id: tlPublic;
|
||||
title: qsTr("Federated")
|
||||
|
@ -68,6 +72,7 @@ Page {
|
|||
height: parent.itemHeight
|
||||
onOpenDrawer: infoPanel.open = setDrawer
|
||||
}
|
||||
|
||||
Item {
|
||||
id: tlSearch;
|
||||
width: parent.itemWidth
|
||||
|
@ -84,6 +89,7 @@ Page {
|
|||
id: loader
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Column {
|
||||
id: headerContainer
|
||||
width: tlSearch.width
|
||||
|
@ -103,6 +109,7 @@ Page {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: loading
|
||||
BusyIndicator {
|
||||
|
@ -111,6 +118,7 @@ Page {
|
|||
running: true
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: tagListComponent
|
||||
MyList {
|
||||
|
@ -135,6 +143,7 @@ Page {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: userListComponent
|
||||
MyList {
|
||||
|
@ -172,9 +181,7 @@ Page {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SlideshowView {
|
||||
|
@ -187,12 +194,9 @@ Page {
|
|||
onCurrentIndexChanged: {
|
||||
navigation.slideshowIndexChanged(currentIndex)
|
||||
}
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: 0
|
||||
top: parent.top
|
||||
topMargin: 0
|
||||
rightMargin: mainPage.isPortrait ? 0 : infoPanel.visibleSize
|
||||
bottomMargin: mainPage.isPortrait ? infoPanel.visibleSize : 0
|
||||
}
|
||||
|
@ -209,11 +213,9 @@ Page {
|
|||
icon.source: "image://theme/icon-l-add"
|
||||
anchors {
|
||||
right: (mainPage.isPortrait ? parent.right : infoPanel.left)
|
||||
rightMargin: Theme.paddingLarge
|
||||
bottom: (mainPage.isPortrait ? infoPanel.top : parent.bottom)
|
||||
margins: {
|
||||
left: Theme.paddingLarge
|
||||
bottom: Theme.paddingLarge
|
||||
}
|
||||
bottomMargin: Theme.paddingLarge
|
||||
}
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("ConversationPage.qml"), {
|
||||
|
@ -242,6 +244,7 @@ Page {
|
|||
Qt.openUrlExternally(href);
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("aaa")
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import QtGraphicalEffects 1.0
|
|||
|
||||
Page {
|
||||
id: profilePage
|
||||
|
||||
property ListModel tweets
|
||||
property string display_name: ""
|
||||
property string username: ""
|
||||
|
@ -141,27 +142,28 @@ Page {
|
|||
image: profileImage
|
||||
bg: profileBackground
|
||||
}
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: expander.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
clip: true
|
||||
mdl: ListModel {}
|
||||
type: "accounts/"+user_id+"/statuses"
|
||||
vars: {}
|
||||
conf: Logic.conf
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: profileExpander.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
}
|
||||
|
||||
// ProfilePage ExpandingSection
|
||||
ExpandingSectionGroup {
|
||||
id: expander
|
||||
id: profileExpander
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
ExpandingSection {
|
||||
id: expandingSection1
|
||||
title: qsTr("About")
|
||||
|
@ -172,22 +174,23 @@ Page {
|
|||
|
||||
Rectangle {
|
||||
id: txtContainer
|
||||
width: expander.width
|
||||
width: parent.width
|
||||
height: Math.min(txtNote.height, parent.height*0.488)
|
||||
color: "transparent"
|
||||
visible: {
|
||||
if ((note.text === "") && (note.text === "<p></p>") ) {
|
||||
if ((note.text === "") || (note.text === "<p></p>") ) {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
SilicaListView {
|
||||
id: txtFlickable
|
||||
anchors.fill: txtContainer
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
quickScroll: false
|
||||
VerticalScrollDecorator { flickable: txtNote }
|
||||
VerticalScrollDecorator {}
|
||||
|
||||
Text {
|
||||
id: txtNote
|
||||
|
@ -228,6 +231,7 @@ Page {
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.leftMargin: Theme.paddingLarge
|
||||
anchors.rightMargin: Theme.paddingLarge
|
||||
|
||||
Text {
|
||||
id: txtFollowers
|
||||
visible: followers_count ? true : false
|
||||
|
@ -236,6 +240,7 @@ Page {
|
|||
color: Theme.highlightColor
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Text {
|
||||
id: txtFollowing
|
||||
visible: following_count ? true : false
|
||||
|
@ -244,6 +249,7 @@ Page {
|
|||
color: Theme.highlightColor
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Text {
|
||||
id: txtStatuses
|
||||
visible: statuses_count ? true : false
|
||||
|
@ -252,6 +258,7 @@ Page {
|
|||
color: Theme.highlightColor
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
/*Text {
|
||||
id: txtFavourites
|
||||
visible: favourites_count ? true : false
|
||||
|
@ -304,11 +311,12 @@ Page {
|
|||
// to-do: create notification banner "Follow request sent!"
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: btnMute
|
||||
preferredWidth: Theme.buttonWidthSmall
|
||||
text: (muting ? qsTr("Unmute") : qsTr("Mute"))
|
||||
color: (muting ? highlightColor : palette.primaryColor)
|
||||
color: (muting ? palette.errorColor : palette.primaryColor)
|
||||
onClicked: {
|
||||
var msg = {
|
||||
'method' : 'POST',
|
||||
|
@ -319,6 +327,7 @@ Page {
|
|||
worker.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: btnBlock
|
||||
preferredWidth: Theme.buttonWidthSmall
|
||||
|
|
|
@ -5,33 +5,86 @@ import "../lib/API.js" as Logic
|
|||
|
||||
Page {
|
||||
id: settingsPage
|
||||
allowedOrientations: Orientation.All
|
||||
|
||||
SilicaFlickable {
|
||||
anchors.fill: parent
|
||||
contentHeight: column.height + Theme.paddingLarge
|
||||
contentWidth: parent.width
|
||||
anchors.fill: parent
|
||||
|
||||
RemorsePopup { id: remorsePopup }
|
||||
|
||||
VerticalScrollDecorator {}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
spacing: Theme.paddingSmall
|
||||
spacing: Theme.paddingMedium
|
||||
width: parent.width
|
||||
|
||||
PageHeader {
|
||||
title: qsTr("Settings")
|
||||
}
|
||||
Column {
|
||||
// No spacing in this column
|
||||
width: parent.width
|
||||
|
||||
SectionHeader { text: "Options"}
|
||||
|
||||
IconTextSwitch {
|
||||
text: qsTr("Load Images in Toots")
|
||||
description: qsTr("Disable this option if you want to preserve your data connection")
|
||||
icon.source: "image://theme/icon-m-image"
|
||||
enabled: true
|
||||
checked: typeof Logic.conf['loadImages'] !== "undefined" && Logic.conf['loadImages']
|
||||
onClicked: {
|
||||
Logic.conf['loadImages'] = checked
|
||||
}
|
||||
}
|
||||
|
||||
IconTextSwitch {
|
||||
text: qsTr("Use smaller Font Size in Toots")
|
||||
description: qsTr("Enable this option if you prefer to use a smaller font size in displayed Toots")
|
||||
icon.source: "image://theme/icon-m-font-size"
|
||||
enabled: false
|
||||
//checked: typeof Logic.conf['loadImages'] !== "undefined" && Logic.conf['loadImages']
|
||||
//onClicked: {
|
||||
// Logic.conf['loadImages'] = checked
|
||||
//}
|
||||
}
|
||||
|
||||
SectionHeader { text: "Account"}
|
||||
|
||||
Item {
|
||||
id: removeAccount
|
||||
width: parent.width
|
||||
height: txtRemoveAccount.height + btnRemoveAccount.height + Theme.paddingLarge
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: Theme.paddingLarge
|
||||
right: parent.right
|
||||
rightMargin: Theme.paddingLarge
|
||||
}
|
||||
|
||||
Icon {
|
||||
id: icnRemoveAccount
|
||||
color: Theme.secondaryColor
|
||||
width: Theme.iconSizeMedium
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: Logic.conf['login'] ? "image://theme/icon-m-contact" : "image://theme/icon-m-add"
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
Column {
|
||||
id: clnRemoveAccount
|
||||
spacing: Theme.paddingMedium
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: icnRemoveAccount.left
|
||||
}
|
||||
|
||||
Button {
|
||||
id: btnRemoveAccount
|
||||
text: Logic.conf['login'] ? qsTr("Remove Account") : qsTr("Add Account")
|
||||
description: Logic.conf['login'] ? qsTr("Deauthorize this app and remove your account") : qsTr("Authorize this app to access your Mastodon account")
|
||||
icon.source: Logic.conf['login'] ? "image://theme/icon-m-contact" : "image://theme/icon-m-add"
|
||||
onCheckedChanged: {
|
||||
remorsePopup.execute(removeAccount.text, function() {
|
||||
busy = true;
|
||||
checked = false;
|
||||
timer1.start();
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
onClicked: {
|
||||
remorsePopup.execute(btnRemoveAccount.text, function() {
|
||||
if (Logic.conf['login']) {
|
||||
Logic.conf['login'] = false
|
||||
Logic.conf['instance'] = null;
|
||||
|
@ -40,10 +93,7 @@ Page {
|
|||
pageStack.push(Qt.resolvedUrl("LoginPage.qml"))
|
||||
})
|
||||
}
|
||||
/* busy = true;
|
||||
checked = false;
|
||||
timer1.start()
|
||||
}*/
|
||||
|
||||
Timer {
|
||||
id: timer1
|
||||
interval: 4700
|
||||
|
@ -51,16 +101,23 @@ Page {
|
|||
}
|
||||
}
|
||||
|
||||
IconTextSwitch {
|
||||
//enabled: false
|
||||
checked: typeof Logic.conf['loadImages'] !== "undefined" && Logic.conf['loadImages']
|
||||
text: qsTr("Load images in toots")
|
||||
description: qsTr("Disable this option if you want to preserve your data connection")
|
||||
icon.source: "image://theme/icon-m-image"
|
||||
onClicked: {
|
||||
Logic.conf['loadImages'] = checked
|
||||
Label {
|
||||
id: txtRemoveAccount
|
||||
text: Logic.conf['login'] ? qsTr("Deauthorize this app from using your account and remove account data from phone") : qsTr("Authorize this app to access your Mastodon account")
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
wrapMode: Text.Wrap
|
||||
color: Theme.secondaryColor
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: Theme.paddingLarge * 1.9
|
||||
right: parent.right
|
||||
rightMargin: Theme.paddingLarge * 1.2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SectionHeader { text: "Support"}
|
||||
|
||||
IconTextSwitch {
|
||||
text: qsTr("Translate")
|
||||
|
@ -77,8 +134,7 @@ Page {
|
|||
interval: 4700
|
||||
onTriggered: parent.busy = false
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
SectionHeader {
|
||||
text: qsTr("Credits")
|
||||
|
@ -89,52 +145,61 @@ Page {
|
|||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
rightMargin: Theme.paddingLarge
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: ListModel {
|
||||
|
||||
ListElement {
|
||||
name: "Duško Angirević"
|
||||
desc: qsTr("UI/UX design and development")
|
||||
mastodon: "dysko@mastodon.social"
|
||||
mail: ""
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Miodrag Nikolić"
|
||||
desc: qsTr("Visual identity")
|
||||
mastodon: ""
|
||||
mail: "micotakis@gmail.com"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Molan"
|
||||
desc: qsTr("Development and translations")
|
||||
mastodon: "molan@fosstodon.org"
|
||||
mail: ""
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Quentin PAGÈS / Quenti ♏"
|
||||
desc: qsTr("Occitan & French translation")
|
||||
mastodon: "Quenti@framapiaf.org"
|
||||
mail: ""
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Luchy Kon / dashinfantry"
|
||||
desc: qsTr("Chinese translation")
|
||||
mastodon: ""
|
||||
mail: "dashinfantry@gmail.com"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "André Koot"
|
||||
desc: qsTr("Dutch translation")
|
||||
mastodon: "meneer@mastodon.social"
|
||||
mail: "https://twitter.com/meneer"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "CarmenFdez"
|
||||
desc: qsTr("Spanish translation")
|
||||
mastodon: ""
|
||||
mail: ""
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Mohamed-Touhami MAHDI"
|
||||
desc: qsTr("Added README file")
|
||||
|
@ -146,31 +211,29 @@ Page {
|
|||
Item {
|
||||
width: parent.width
|
||||
height: Theme.itemSizeMedium
|
||||
|
||||
IconButton {
|
||||
id: btn
|
||||
icon.source: "image://theme/" + (model.mastodon !== "" ? "icon-m-outline-chat" : "icon-m-mail") + "?" + (pressed
|
||||
? Theme.highlightColor : Theme.primaryColor)
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
}
|
||||
icon.source: "image://theme/" + (model.mastodon !== "" ? "icon-m-contact" : "icon-m-mail") + "?" + (pressed
|
||||
? Theme.highlightColor
|
||||
: Theme.primaryColor)
|
||||
onClicked: {
|
||||
if (model.mastodon !== ""){
|
||||
var m = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
|
||||
pageStack.push(Qt.resolvedUrl("ConversationPage.qml"), {
|
||||
toot_id: 0,
|
||||
title: model.name,
|
||||
headerTitle: "Mention",
|
||||
description: '@'+model.mastodon,
|
||||
avatar: "",
|
||||
mdl: m,
|
||||
type: "reply"
|
||||
type: "new"
|
||||
})
|
||||
} else {
|
||||
Qt.openUrlExternally("mailto:"+model.mail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
|
@ -183,9 +246,10 @@ Page {
|
|||
Label {
|
||||
id: lblName
|
||||
text: model.name
|
||||
color: Theme.secondaryColor
|
||||
color: Theme.highlightColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
}
|
||||
|
||||
Label {
|
||||
text: model.desc
|
||||
color: Theme.secondaryHighlightColor
|
||||
|
|
|
@ -4,6 +4,7 @@ import Sailfish.Silica 1.0
|
|||
|
||||
Component {
|
||||
id: emojiComponent
|
||||
|
||||
Dialog {
|
||||
id: emoticonsDialog
|
||||
canAccept: false //selector.currentIndex >= 0
|
||||
|
@ -13,20 +14,17 @@ Component {
|
|||
// acceptDestinationInstance.category = selector.value
|
||||
}
|
||||
}
|
||||
|
||||
SilicaGridView {
|
||||
id: gridView
|
||||
anchors.fill: parent
|
||||
//anchors.rightMargin: Theme.paddingLarge
|
||||
//anchors.leftMargin: Theme.paddingLarge
|
||||
cellWidth: gridView.width / 6
|
||||
cellHeight: cellWidth
|
||||
VerticalScrollDecorator {flickable: listEmojis }
|
||||
header: PageHeader {
|
||||
title: qsTr("Emojis")
|
||||
description: qsTr("Tap to insert")
|
||||
}
|
||||
cellWidth: gridView.width / 6
|
||||
cellHeight: cellWidth
|
||||
anchors.fill: parent
|
||||
model: ListModel {
|
||||
id: listEmojis
|
||||
ListElement { section: "smileys"; glyph: "😁" }
|
||||
ListElement { section: "smileys"; glyph: "😂" }
|
||||
ListElement { section: "smileys"; glyph: "😃" }
|
||||
|
@ -142,11 +140,12 @@ Component {
|
|||
delegate: BackgroundItem {
|
||||
width: gridView.cellWidth
|
||||
height: gridView.cellHeight
|
||||
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
color: (highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
text: glyph
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: (highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
onClicked: {
|
||||
var cursorPosition = toot.cursorPosition
|
||||
|
@ -158,6 +157,8 @@ Component {
|
|||
emoticonsDialog.accept()
|
||||
}
|
||||
}
|
||||
|
||||
VerticalScrollDecorator {flickable: listEmojis }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,28 +4,24 @@ import Sailfish.Silica 1.0
|
|||
|
||||
DockedPanel {
|
||||
id: root
|
||||
z: 100
|
||||
dock: Dock.Top
|
||||
width: parent.width
|
||||
height: content.height
|
||||
dock: Dock.Top
|
||||
|
||||
Rectangle {
|
||||
id: content
|
||||
width: root.width
|
||||
height: infoLabel.height + 5*Theme.paddingMedium
|
||||
//anchors.topMargin: 20
|
||||
color: Theme.highlightBackgroundColor
|
||||
opacity: 1.0
|
||||
width: root.width
|
||||
height: infoLabel.height + 3*Theme.paddingMedium
|
||||
|
||||
Label {
|
||||
id: infoLabel
|
||||
text : ""
|
||||
color: Theme.primaryColor
|
||||
font.family: Theme.fontFamilyHeading
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
//font.weight: Font.Bold
|
||||
width: parent.width
|
||||
color: Theme.highlightColor
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: parent.width
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: Theme.horizontalPageMargin*2
|
||||
|
@ -34,6 +30,7 @@ DockedPanel {
|
|||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
|
|
|
@ -4,9 +4,11 @@ import Sailfish.Silica 1.0
|
|||
|
||||
BackgroundItem {
|
||||
id: delegate
|
||||
|
||||
signal openUser (string notice)
|
||||
height: Theme.itemSizeMedium
|
||||
|
||||
width: parent.width
|
||||
height: Theme.itemSizeMedium
|
||||
|
||||
Rectangle {
|
||||
id: avatar
|
||||
|
@ -23,6 +25,7 @@ BackgroundItem {
|
|||
anchors.fill: parent
|
||||
source: model.account_avatar
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
size: BusyIndicatorSize.Small
|
||||
opacity: img.status === Image.Ready ? 0.0 : 1.0
|
||||
|
@ -30,6 +33,7 @@ BackgroundItem {
|
|||
running: avatar.status !== Image.Ready;
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("./../ProfilePage.qml"), {
|
||||
|
|
|
@ -4,10 +4,12 @@ import QtMultimedia 5.0
|
|||
|
||||
|
||||
Item {
|
||||
id: holder
|
||||
|
||||
property ListModel model
|
||||
property double wRatio : 16/9
|
||||
property double hRatio : 9/16
|
||||
id: holder
|
||||
|
||||
width: width
|
||||
height: height
|
||||
Component.onCompleted: {
|
||||
|
@ -92,6 +94,7 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MyImage {
|
||||
id: placeholder2
|
||||
width: 2
|
||||
|
@ -110,6 +113,7 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MyImage {
|
||||
id: placeholder3
|
||||
width: 2
|
||||
|
@ -128,6 +132,7 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
MyImage {
|
||||
id: placeholder4
|
||||
width: 2
|
||||
|
|
|
@ -4,12 +4,13 @@ import QtMultimedia 5.0
|
|||
|
||||
|
||||
FullscreenContentPage {
|
||||
id: mediaPage
|
||||
allowedOrientations: Orientation.All
|
||||
|
||||
property string type: ""
|
||||
property string previewURL: ""
|
||||
property string mediaURL: ""
|
||||
|
||||
id: imagePage
|
||||
allowedOrientations: Orientation.All
|
||||
Component.onCompleted: function(){
|
||||
console.log(type)
|
||||
console.log(previewURL)
|
||||
|
@ -29,8 +30,6 @@ FullscreenContentPage {
|
|||
id: videoFlickable
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
contentWidth: imageContainer.width
|
||||
contentHeight: imageContainer.height
|
||||
clip: true
|
||||
|
||||
Image {
|
||||
|
@ -57,7 +56,6 @@ FullscreenContentPage {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
onPlaybackStateChanged: {
|
||||
console.log(playbackState)
|
||||
switch (playbackState){
|
||||
|
@ -72,7 +70,6 @@ FullscreenContentPage {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
onPositionChanged: function(){
|
||||
//console.log(duration)
|
||||
//console.log(bufferProgress)
|
||||
|
@ -84,17 +81,18 @@ FullscreenContentPage {
|
|||
playerProgress.value = position
|
||||
}
|
||||
}
|
||||
|
||||
onStopped: function(){
|
||||
stop()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: playerIcon
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.leftMargin: Theme.paddingLarge
|
||||
anchors.bottomMargin: Theme.paddingLarge*1.5
|
||||
anchors {
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
bottomMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
icon.source: "image://theme/icon-m-play"
|
||||
onClicked: function() {
|
||||
if (video.playbackState === MediaPlayer.PlayingState)
|
||||
|
@ -105,26 +103,15 @@ FullscreenContentPage {
|
|||
}
|
||||
|
||||
ProgressBar {
|
||||
indeterminate: true
|
||||
id: playerProgress
|
||||
anchors.left: playerIcon.right
|
||||
anchors.right: videoDlBtn.left
|
||||
anchors.verticalCenter: playerIcon.verticalCenter
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottomMargin: Theme.paddingLarge*1.5
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: videoDlBtn
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.rightMargin: Theme.paddingLarge
|
||||
anchors.bottomMargin: Theme.paddingLarge*1.5
|
||||
icon.source: "image://theme/icon-m-cloud-download"
|
||||
onClicked: {
|
||||
var filename = mediaURL.split("/");
|
||||
FileDownloader.downloadFile(mediaURL, filename[filename.length-1]);
|
||||
}
|
||||
indeterminate: true
|
||||
width: 400
|
||||
anchors {
|
||||
verticalCenter: playerIcon.verticalCenter
|
||||
left: playerIcon.right
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin + Theme.iconSizeMedium
|
||||
bottomMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
@ -135,16 +122,17 @@ FullscreenContentPage {
|
|||
color: Theme.highlightDimmerColor
|
||||
height: videoError.height + 2*Theme.paddingMedium
|
||||
width: parent.width
|
||||
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
id: videoError
|
||||
width: parent.width - 2*Theme.paddingMedium
|
||||
wrapMode: Text.Wrap
|
||||
height: contentHeight
|
||||
visible: false;
|
||||
font.pixelSize: Theme.fontSizeSmall;
|
||||
visible: false
|
||||
text: video.errorString
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.highlightColor
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width - 2*Theme.paddingMedium
|
||||
height: contentHeight
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,15 +147,17 @@ FullscreenContentPage {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: imageFlickable
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
contentWidth: imageContainer.width
|
||||
contentHeight: imageContainer.height
|
||||
contentWidth: imageContainer.width; contentHeight: imageContainer.height
|
||||
clip: true
|
||||
onHeightChanged: if (imagePreview.status === Image.Ready) imagePreview.fitToScreen();
|
||||
anchors.fill: parent
|
||||
onHeightChanged: if (imagePreview.status === Image.Ready) {
|
||||
imagePreview.fitToScreen()
|
||||
}
|
||||
|
||||
Item {
|
||||
id: imageContainer
|
||||
|
@ -176,18 +166,21 @@ FullscreenContentPage {
|
|||
|
||||
Image {
|
||||
id: imagePreview
|
||||
|
||||
property real prevScale
|
||||
|
||||
function fitToScreen() {
|
||||
scale = Math.min(imageFlickable.width / width, imageFlickable.height / height, 1)
|
||||
scale = Math.min(imageFlickable.width / width, imageFlickable.height / height, imageFlickable.width, imageFlickable.height)
|
||||
pinchArea.minScale = scale
|
||||
prevScale = scale
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
cache: true
|
||||
asynchronous: true
|
||||
sourceSize.height: 2000;
|
||||
smooth: true // might slower performance
|
||||
sourceSize.width: mediaPage.width
|
||||
smooth: false
|
||||
anchors.centerIn: parent
|
||||
onStatusChanged: {
|
||||
if (status == Image.Ready) {
|
||||
fitToScreen()
|
||||
|
@ -195,15 +188,6 @@ FullscreenContentPage {
|
|||
}
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: loadedAnimation
|
||||
target: imagePreview
|
||||
property: "opacity"
|
||||
duration: 250
|
||||
from: 0; to: 1
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
|
||||
onScaleChanged: {
|
||||
if ((width * scale) > imageFlickable.width) {
|
||||
var xoff = (imageFlickable.width / 2 + imageFlickable.contentX) * scale / prevScale;
|
||||
|
@ -215,19 +199,30 @@ FullscreenContentPage {
|
|||
}
|
||||
prevScale = scale
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: loadedAnimation
|
||||
target: imagePreview
|
||||
property: "opacity"
|
||||
duration: 250
|
||||
from: 0; to: 1
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PinchArea {
|
||||
id: pinchArea
|
||||
opacity: 0.3
|
||||
|
||||
property real minScale: 1.0
|
||||
property real maxScale: 3.0
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: imagePreview.status === Image.Ready
|
||||
pinch.target: imagePreview
|
||||
pinch.minimumScale: minScale * 0.5 // This is to create "bounce back effect"
|
||||
pinch.maximumScale: maxScale * 1.5 // when over zoomed
|
||||
pinch.maximumScale: maxScale * 1.5 // when over zoomed}
|
||||
|
||||
onPinchFinished: {
|
||||
imageFlickable.returnToBounds()
|
||||
|
@ -249,7 +244,6 @@ FullscreenContentPage {
|
|||
from: imagePreview.scale
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
anchors.centerIn: parent
|
||||
|
@ -266,18 +260,16 @@ FullscreenContentPage {
|
|||
|
||||
Component {
|
||||
id: loadingIndicator
|
||||
|
||||
Item {
|
||||
width: mediaPage.width
|
||||
height: childrenRect.height
|
||||
width: imagePage.width
|
||||
|
||||
ProgressCircle {
|
||||
id: imageLoadingIndicator
|
||||
progressValue: imagePreview.progress
|
||||
progressColor: inAlternateCycle ? Theme.highlightColor : Theme.highlightDimmerColor
|
||||
backgroundColor: inAlternateCycle ? Theme.highlightDimmerColor : Theme.highlightColor
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
progressValue: imagePreview.progress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -285,31 +277,41 @@ FullscreenContentPage {
|
|||
Component {
|
||||
id: failedLoading
|
||||
Text {
|
||||
font.pixelSize: Theme.fontSizeSmall;
|
||||
text: qsTr("Error loading")
|
||||
font.pixelSize: Theme.fontSizeSmall;
|
||||
color: Theme.highlightColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerticalScrollDecorator { flickable: imageFlickable }
|
||||
}
|
||||
|
||||
IconButton {
|
||||
y: Theme.paddingLarge
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.horizontalPageMargin
|
||||
id: dismissBtn
|
||||
icon.source: "image://theme/icon-m-dismiss"
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: Theme.horizontalPageMargin
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
onClicked: pageStack.pop()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.rightMargin: Theme.paddingLarge
|
||||
anchors.bottomMargin: Theme.paddingLarge*1.5
|
||||
id: mediaDlBtn
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
bottom: parent.bottom
|
||||
bottomMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
icon.source: "image://theme/icon-m-cloud-download"
|
||||
onClicked: {
|
||||
var filename = mediaURL.split("/");
|
||||
FileDownloader.downloadFile(mediaURL, filename[filename.length-1]);
|
||||
}
|
||||
}
|
||||
|
||||
VerticalScrollDecorator { flickable: imageFlickable }
|
||||
}
|
||||
|
|
@ -37,26 +37,24 @@ Item {
|
|||
width: account_locked ? Theme.iconSizeExtraSmall*0.8 : 0
|
||||
opacity: 0.8
|
||||
height: width
|
||||
source: "image://theme/icon-s-secure?" + (pressed
|
||||
? Theme.highlightColor
|
||||
: Theme.primaryColor)
|
||||
source: "image://theme/icon-s-secure?" + (pressed ? Theme.highlightColor : Theme.primaryColor)
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblScreenName
|
||||
truncationMode: TruncationMode.Fade
|
||||
text: '@'+account_username
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
||||
anchors {
|
||||
left: iconVerified.right
|
||||
right: lblDate.left
|
||||
leftMargin: Theme.paddingMedium
|
||||
baseline: lblName.baseline
|
||||
}
|
||||
truncationMode: TruncationMode.Fade
|
||||
text: '@'+account_username
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
||||
}
|
||||
Label {
|
||||
|
||||
Label {
|
||||
id: lblDate
|
||||
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
|
||||
text: Format.formatDate(created_at, new Date() - created_at < 60*60*1000 ? Formatter.DurationElapsedShort : Formatter.TimeValueTwentyFourHours)
|
||||
|
@ -64,8 +62,8 @@ Item {
|
|||
horizontalAlignment: Text.AlignRight
|
||||
anchors {
|
||||
right: parent.right
|
||||
baseline: lblName.baseline
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
baseline: lblName.baseline
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ Item {
|
|||
width: parent.width
|
||||
Image {
|
||||
id: icon
|
||||
visible: type.length
|
||||
width: Theme.iconSizeExtraSmall
|
||||
height: width
|
||||
source: typeof typeIcon !== "undefined" ? typeIcon : ""
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: Theme.paddingMedium
|
||||
|
@ -16,12 +20,8 @@ Item {
|
|||
left: parent.left
|
||||
leftMargin: Theme.horizontalPageMargin + Theme.iconSizeMedium - width
|
||||
}
|
||||
visible: type.length
|
||||
width: Theme.iconSizeExtraSmall
|
||||
height: width
|
||||
source: typeof typeIcon !== "undefined" ? typeIcon : ""
|
||||
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblRtByName
|
||||
visible: type.length
|
||||
|
@ -48,7 +48,6 @@ Item {
|
|||
}
|
||||
return typeof reblog_account_username !== "undefined" ? '@' + reblog_account_username + ' ' + action : ''
|
||||
}
|
||||
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
color: Theme.highlightColor
|
||||
}
|
||||
|
|
|
@ -5,33 +5,38 @@ import QtMultimedia 5.0
|
|||
|
||||
Item {
|
||||
id: myImage
|
||||
|
||||
property string type : ""
|
||||
property string previewURL: ""
|
||||
property string mediaURL: ""
|
||||
|
||||
Rectangle {
|
||||
opacity: 0.2
|
||||
anchors.fill: parent
|
||||
color: Theme.highlightDimmerColor
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: "image://theme/icon-m-image"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: progressRec
|
||||
anchors.bottom: parent.bottom
|
||||
width: 0
|
||||
height: Theme.paddingSmall
|
||||
color: Theme.highlightBackgroundColor
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
||||
Image {
|
||||
id: img
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimator {} }
|
||||
source: previewURL
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
anchors.fill: parent
|
||||
onProgressChanged: {
|
||||
if (progress != 1)
|
||||
progressRec.width = parent.width * progress
|
||||
|
@ -39,35 +44,48 @@ Item {
|
|||
progressRec.width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("./ImageFullScreen.qml"), {"previewURL": previewURL, "mediaURL": mediaURL, "type": type})
|
||||
pageStack.push(Qt.resolvedUrl("./MediaFullScreen.qml"), {
|
||||
"previewURL": previewURL,
|
||||
"mediaURL": mediaURL,
|
||||
"type": type
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: videoIcon
|
||||
visible: type === "video" || type === "gifv"
|
||||
anchors.centerIn: parent
|
||||
source: "image://theme/icon-l-play"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: mediaLoader
|
||||
size: BusyIndicatorSize.Large
|
||||
running: img.status !== Image.Ready
|
||||
opacity: img.status === Image.Ready ? 0.0 : 1.0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
id: mediaWarning
|
||||
color: Theme.highlightDimmerColor
|
||||
visible: typeof status_sensitive != 'undefined' && status_sensitive ? true : false
|
||||
anchors.fill: parent
|
||||
|
||||
Image {
|
||||
source: "image://theme/icon-l-attention?"+Theme.highlightColor
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: parent.visible = false;
|
||||
onClicked: parent.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,13 +61,7 @@ SilicaListView {
|
|||
pageStack.push(Qt.resolvedUrl("../SettingsPage.qml"), {})
|
||||
}
|
||||
}
|
||||
/* MenuItem {
|
||||
text: qsTr("Open in Browser")
|
||||
visible: profile_url != ""
|
||||
onClicked: {
|
||||
Clipboard.text = profile_url
|
||||
}
|
||||
} */
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Load more")
|
||||
onClicked: {
|
||||
|
|
|
@ -4,13 +4,16 @@ import QtGraphicalEffects 1.0
|
|||
|
||||
|
||||
SilicaGridView {
|
||||
id: gridView
|
||||
|
||||
property bool isPortrait: false
|
||||
signal slideshowShow(int vIndex)
|
||||
signal slideshowIndexChanged(int vIndex)
|
||||
|
||||
onSlideshowIndexChanged: {
|
||||
navigateTo(vIndex)
|
||||
}
|
||||
id: gridView
|
||||
property bool isPortrait: false
|
||||
|
||||
ListModel {
|
||||
id: listModel
|
||||
ListElement {
|
||||
|
@ -20,12 +23,14 @@ SilicaGridView {
|
|||
active: true
|
||||
unread: false
|
||||
}
|
||||
|
||||
ListElement {
|
||||
icon: "image://theme/icon-m-alarm"
|
||||
slug: "notifications"
|
||||
name: "Notifications"
|
||||
active: false
|
||||
}
|
||||
|
||||
ListElement {
|
||||
icon: "image://theme/icon-m-whereami"
|
||||
slug: "local"
|
||||
|
@ -33,6 +38,7 @@ SilicaGridView {
|
|||
active: false
|
||||
unread: false
|
||||
}
|
||||
|
||||
ListElement {
|
||||
icon: "image://theme/icon-m-website"
|
||||
slug: "federated"
|
||||
|
@ -40,6 +46,7 @@ SilicaGridView {
|
|||
active: false
|
||||
unread: false
|
||||
}
|
||||
|
||||
ListElement {
|
||||
icon: "image://theme/icon-m-search"
|
||||
slug: "search"
|
||||
|
@ -49,15 +56,13 @@ SilicaGridView {
|
|||
}
|
||||
}
|
||||
model: listModel
|
||||
anchors.fill: parent
|
||||
currentIndex: -1
|
||||
|
||||
cellWidth: isPortrait ? gridView.width : gridView.width / model.count
|
||||
cellHeight: isPortrait ? gridView.height/model.count : gridView.height
|
||||
|
||||
anchors.fill: parent
|
||||
delegate: BackgroundItem {
|
||||
clip: true
|
||||
id: rectangle
|
||||
clip: true
|
||||
width: gridView.cellWidth
|
||||
height: gridView.cellHeight
|
||||
GridView.onAdd: AddAnimation {
|
||||
|
@ -66,88 +71,93 @@ SilicaGridView {
|
|||
GridView.onRemove: RemoveAnimation {
|
||||
target: rectangle
|
||||
}
|
||||
|
||||
GlassItem {
|
||||
id: effect
|
||||
visible: !isPortrait && unread
|
||||
dimmed: true
|
||||
color: Theme.highlightColor
|
||||
width: Theme.itemSizeMedium
|
||||
height: Theme.itemSizeMedium
|
||||
dimmed: true
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: -height/2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Theme.highlightColor
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
bottomMargin: -height/2
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
GlassItem {
|
||||
id: effect2
|
||||
visible: isPortrait && unread
|
||||
dimmed: false
|
||||
color: Theme.highlightColor
|
||||
width: Theme.itemSizeMedium
|
||||
height: Theme.itemSizeMedium
|
||||
dimmed: false
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: -height/2;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Theme.highlightColor
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: -height/2
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
OpacityRampEffect {
|
||||
sourceItem: label
|
||||
offset: 0.5
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
anchors.fill: image
|
||||
source: image
|
||||
color: (highlighted ? Theme.highlightColor : (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
|
||||
anchors.fill: image
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image
|
||||
visible: false
|
||||
source: model.icon // +'?'+ (highlighted ? Theme.highlightColor : (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
|
||||
sourceSize.width: Theme.iconSizeMedium
|
||||
sourceSize.height: Theme.iconSizeMedium
|
||||
source: model.icon// +'?'+ (highlighted ? Theme.highlightColor : (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
|
||||
anchors.centerIn: parent
|
||||
visible: false
|
||||
// smooth: true
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: Theme.paddingSmall
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: false
|
||||
text: model.name
|
||||
font.pixelSize: Theme.fontSizeExtraSmall/2
|
||||
color: (highlighted
|
||||
? Theme.highlightColor
|
||||
: (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
bottomMargin: Theme.paddingSmall
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: label
|
||||
visible: false
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
}
|
||||
horizontalAlignment : Text.AlignHCente
|
||||
width: parent.width
|
||||
color: (highlighted ? Theme.highlightColor : Theme.secondaryHighlightColor)
|
||||
|
||||
text: {
|
||||
return model.name.toUpperCase();
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
font.family: Theme.fontFamilyHeading
|
||||
width: parent.width
|
||||
horizontalAlignment : Text.AlignHCenter
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
||||
font {
|
||||
pixelSize: Theme.fontSizeExtraSmall
|
||||
family: Theme.fontFamilyHeading
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
slideshowShow(index)
|
||||
console.log(index)
|
||||
navigateTo(model.slug)
|
||||
effect.state = "right"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function navigateTo(slug){
|
||||
for(var i = 0; i < listModel.count; i++){
|
||||
if (listModel.get(i).slug === slug || i===slug)
|
||||
|
@ -156,9 +166,9 @@ SilicaGridView {
|
|||
listModel.setProperty(i, 'active', false);
|
||||
}
|
||||
console.log(slug)
|
||||
|
||||
}
|
||||
|
||||
VerticalScrollDecorator {}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,48 +4,69 @@ import Sailfish.Silica 1.0
|
|||
|
||||
Item {
|
||||
id: profileHeader
|
||||
|
||||
property int value: 0
|
||||
property string title: ""
|
||||
property string description: ""
|
||||
property string image: ""
|
||||
property string bg: ""
|
||||
|
||||
width: parent.width
|
||||
height: icon.height + Theme.paddingLarge*2
|
||||
|
||||
Rectangle {
|
||||
id: bgImage
|
||||
anchors.fill: parent
|
||||
opacity: 0.2
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: Theme.highlightBackgroundColor }
|
||||
GradientStop { position: 1.0; color: Theme.highlightBackgroundColor }
|
||||
}
|
||||
anchors.fill: parent
|
||||
|
||||
Image {
|
||||
anchors.fill: bgImage
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
source: bg
|
||||
opacity: 0.8
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: icon
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: Theme.paddingLarge
|
||||
top: parent.top
|
||||
topMargin: Theme.paddingLarge
|
||||
}
|
||||
asynchronous: true
|
||||
width: description === "" ? Theme.iconSizeMedium : Theme.iconSizeLarge
|
||||
height: width
|
||||
source:
|
||||
if (icon.status === Image.Error)
|
||||
source = "../../images/icon-l-profile.svg?" + (pressed
|
||||
? Theme.highlightColor
|
||||
: Theme.primaryColor)
|
||||
else image
|
||||
width: description === "" ? Theme.iconSizeMedium : Theme.iconSizeLarge
|
||||
height: width
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: Theme.paddingLarge
|
||||
top: parent.top
|
||||
topMargin: Theme.paddingLarge
|
||||
}
|
||||
|
||||
Button {
|
||||
id: imageButton
|
||||
opacity: 0
|
||||
width: Theme.iconSizeExtraLarge * 1.2
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
}
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("ProfileImage.qml"), {
|
||||
"image": image
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors {
|
||||
left: icon.right
|
||||
|
@ -54,6 +75,7 @@ Item {
|
|||
rightMargin: Theme.paddingLarge
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
id: ttl
|
||||
text:
|
||||
|
@ -61,23 +83,24 @@ Item {
|
|||
description.split('@')[0]
|
||||
}
|
||||
else title
|
||||
height: contentHeight
|
||||
color: Theme.highlightColor
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.family: Theme.fontFamilyHeading
|
||||
horizontalAlignment: Text.AlignRight
|
||||
color: Theme.highlightColor
|
||||
truncationMode: TruncationMode.Fade
|
||||
width: parent.width
|
||||
height: contentHeight
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
|
||||
Label {
|
||||
height: description === "" ? 0 : contentHeight
|
||||
text: "@"+description
|
||||
color: Theme.secondaryHighlightColor
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.family: Theme.fontFamilyHeading
|
||||
horizontalAlignment: Text.AlignRight
|
||||
color: Theme.secondaryHighlightColor
|
||||
truncationMode: TruncationMode.Fade
|
||||
width: parent.width
|
||||
height: description === "" ? 0 : contentHeight
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
}
|
||||
|
||||
|
|
27
qml/pages/components/ProfileImage.qml
Normal file
27
qml/pages/components/ProfileImage.qml
Normal file
|
@ -0,0 +1,27 @@
|
|||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
FullscreenContentPage {
|
||||
id: profileImage
|
||||
allowedOrientations: Orientation.All
|
||||
|
||||
property string image: ""
|
||||
|
||||
Image {
|
||||
source: image
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
IconButton {
|
||||
icon.source: "image://theme/icon-m-dismiss"
|
||||
anchors {
|
||||
top: profileImage.top
|
||||
topMargin: Theme.horizontalPageMargin
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
onClicked: pageStack.pop()
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,8 @@ BackgroundItem {
|
|||
visible: type.length
|
||||
anchors.left: lblName.left
|
||||
anchors.bottom: iconRT.bottom
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
color: Theme.secondaryColor
|
||||
text: {
|
||||
var action;
|
||||
switch(type){
|
||||
|
@ -43,8 +45,6 @@ BackgroundItem {
|
|||
}
|
||||
return '@' + retweetScreenName + ' ' + action
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
color: Theme.secondaryColor
|
||||
}
|
||||
|
||||
Image {
|
||||
|
@ -116,12 +116,12 @@ BackgroundItem {
|
|||
}
|
||||
|
||||
Label {
|
||||
id: lblDate
|
||||
function timestamp() {
|
||||
var txt = Format.formatDate(created_at, Formatter.Timepoint)
|
||||
var elapsed = Format.formatDate(created_at, Formatter.DurationElapsedShort)
|
||||
return (elapsed ? elapsed : txt )
|
||||
}
|
||||
id: lblDate
|
||||
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
|
||||
text: Format.formatDate(created_at, new Date() - created_at < 60*60*1000 ? Formatter.DurationElapsedShort : Formatter.TimeValueTwentyFourHours)
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
|
|
|
@ -17,7 +17,7 @@ class Notifications : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Notifications(QObject *parent = 0);
|
||||
explicit Notifications(QObject *parent = nullptr);
|
||||
Q_INVOKABLE void notify(QString appName, QString summary, QString body, bool preview, QString ts, QString issuekey);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue