Compare commits
65 commits
Goober_0_8
...
main
Author | SHA1 | Date | |
---|---|---|---|
31424205e9 | |||
8c1d527068 | |||
bd441eac0e | |||
14e536947b | |||
c1bbb23daf | |||
c322df38c0 | |||
5b0a94eca4 | |||
e883b8dcba | |||
8896b2c076 | |||
dd1a6f1672 | |||
3e9499670d | |||
82d5a1bc0d | |||
fddd407504 | |||
c024f45348 | |||
ecfc81e79c | |||
ae350e9bdd | |||
9e87eafdd7 | |||
8d0a707765 | |||
3b2b578533 | |||
aba4a2bdea | |||
35289499a8 | |||
ebe17fadd7 | |||
8461564c0c | |||
0dc89f87fb | |||
f12a602e4d | |||
97ce9579ec | |||
6473657bf8 | |||
f8fee791bc | |||
bdc5e9ebf5 | |||
8ea6fcaf09 | |||
e386981bec | |||
91ab0585f6 | |||
57f6d128c5 | |||
17590d3c5a | |||
ec769a3771 | |||
3a2dee0979 | |||
fde3a7cdec | |||
f298fe7f61 | |||
c00e68164c | |||
a44de91b3a | |||
cc9520525e | |||
75e98014f4 | |||
dd0190ad8b | |||
12aed636ea | |||
f1ce4d39db | |||
ce0a6d8459 | |||
d5c4d01412 | |||
9e18b77294 | |||
49d58341c3 | |||
cf0919d06a | |||
b5bfd3e09e | |||
58d094a6d5 | |||
1307bb2f2a | |||
b7dc358c33 | |||
6f41f3b948 | |||
3ec3521b38 | |||
baf15b623a | |||
18f100b55e | |||
0ed88761f9 | |||
8378e71435 | |||
f954e15fb6 | |||
e525492bc6 | |||
fdb0b22ee4 | |||
282f3e1b0b | |||
d2fd41d81e |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@ translations/*.qm
|
|||
.settings/
|
||||
src/globals.h
|
||||
buildnum
|
||||
assets/.assets.index
|
||||
|
|
128
CHANGELOG.md
Normal file
128
CHANGELOG.md
Normal file
|
@ -0,0 +1,128 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [0.9.5] - 2020-02-16
|
||||
### Fixed
|
||||
- Refresh post following a repost (issue #57)
|
||||
- Fix HTML parsing on user descriptions (issue #56)
|
||||
- Fix parsing of links containing & (issue #54)
|
||||
|
||||
## [0.9.4] - 2020-02-01
|
||||
### Fixed
|
||||
- Updated longpost url (issue #53)
|
||||
- Rendering posts with links containing surrogate pair characters
|
||||
|
||||
## [0.9.3] - 2019-10-13
|
||||
### Fixed
|
||||
- Don't count markdown links against total post text count (issue #52)
|
||||
- Handle utf8 text copying to the clipboard (issue #25)
|
||||
|
||||
## [0.9.2] - 2019-08-10
|
||||
### Fixed
|
||||
- Authentication error with new install on 10.3.3 devices (issue #49)
|
||||
- Own username populating as mention in replies (issue #51)
|
||||
|
||||
### Changed
|
||||
- Optimized calls for raw to only posts (issue #50)
|
||||
- New changelog format (issue #41)
|
||||
|
||||
## [0.9.1] - 2018-01-15
|
||||
### Fixed
|
||||
- replace html parsing with text rendering and link parsing function (issue #37)
|
||||
- split the avatar images into a seperate cache
|
||||
|
||||
## [0.9.0] - 2017-11-18
|
||||
### Added
|
||||
- settings to prevent image loading
|
||||
|
||||
### Changed
|
||||
- replaced webimageview class with netimagemanager class
|
||||
- open images in preview card
|
||||
|
||||
### Fixed
|
||||
- set minimum avatar size (issue #33)
|
||||
- add raw paramater on bookmark and repost calls (issue #24)
|
||||
- increase initial count (issue #19)
|
||||
- added missing active tab settings (issue #26)
|
||||
- image loading on thread view
|
||||
- simulator builds
|
||||
|
||||
## [0.8.0] - 2017-02-18
|
||||
### Added
|
||||
- invoke hooks for sharing posts (issue #15)
|
||||
- added copy text to clipboard (issue #7)
|
||||
- render oembed photos (issue #12)
|
||||
|
||||
### Fixed
|
||||
- post rendering problems (issue #18)
|
||||
|
||||
## [0.7.0] - 2017-02-07
|
||||
### Fixed
|
||||
- handle bookmark status update (issue #10)
|
||||
- tweak navigation focus policy for BlackBerry Classic (issue #9)
|
||||
- markdown link rendering (issue #4)
|
||||
- oauth work around for 10.3.3 security update (issue #11)
|
||||
- fixed project setup removing hard coded system paths
|
||||
|
||||
## [0.6.0] - 2016-11-13
|
||||
### Added
|
||||
- Added posts, following, and followers view to profile page
|
||||
- Added support for changing visual theme (dark mode)
|
||||
|
||||
### Fixed
|
||||
- Fixed reply-all from thread view page
|
||||
|
||||
## [0.5.0] - 2016-11-05
|
||||
### Added
|
||||
- about page
|
||||
- setting for CC on reply all
|
||||
- bookmark tab
|
||||
- delete post
|
||||
- keyboard shortcuts
|
||||
|
||||
## [0.4.0] - 2016-10-22
|
||||
### Added
|
||||
- mentions tab
|
||||
- link to new root CA on login page
|
||||
- user interactions (follow, block, mute)
|
||||
|
||||
### Changed
|
||||
- app cover reflects unread for active tab
|
||||
|
||||
### Fixed
|
||||
- profile display on small screens
|
||||
|
||||
## [0.3.0] - 2016-10-01
|
||||
### Added
|
||||
- pull to load new posts
|
||||
- add/remove bookmarks
|
||||
- repost and quote posts
|
||||
|
||||
### Fixed
|
||||
- login and logout
|
||||
|
||||
## [0.2.0] - 2016-09-24
|
||||
### Added
|
||||
- thread view
|
||||
- post status icons
|
||||
|
||||
## [0.1.0] - 2016-09-22
|
||||
### Added
|
||||
- Initial release
|
||||
|
||||
[0.9.5]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/0.9.5
|
||||
[0.9.4]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/0.9.4
|
||||
[0.9.3]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/0.9.3
|
||||
[0.9.2]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/0.9.2
|
||||
[0.9.1]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_9_1
|
||||
[0.9.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_9_0
|
||||
[0.8.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_8_0
|
||||
[0.7.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_7_0
|
||||
[0.6.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_6_0
|
||||
[0.5.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_5_0
|
||||
[0.4.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_4_0
|
||||
[0.3.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_3_0
|
||||
[0.2.0]: https://gitlab.dreamfall.space/thrrgilag/goober-bb10/-/tags/Goober_0_2_0
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
* Sat Nov 12 2016 Morgan McMillian <gilag@monkeystew.com> 0.6.0
|
||||
- Fixed reply-all from thread view page
|
||||
- Added posts, following, and followers view to profile page
|
||||
- Added support for changing visual theme (dark mode)
|
|
@ -5,3 +5,11 @@ LIBS += -lbbdata -lbbsystem -lbb
|
|||
QT += network
|
||||
|
||||
include(config.pri)
|
||||
|
||||
simulator {
|
||||
INCLUDEPATH += $$quote($$BASEDIR/../bb-cascades-oauth/oauth)
|
||||
DEPENDPATH += $$quote($$BASEDIR/../bb-cascades-oauth/oauth)
|
||||
LIBS += -lkqoauth
|
||||
LIBS += $$quote(-L$$BASEDIR/../bb-cascades-oauth/oauth/o-g)
|
||||
PRE_TARGETDEPS += $$quote($$BASEDIR/../bb-cascades-oauth/oauth/o-g)
|
||||
}
|
||||
|
|
|
@ -1,50 +1,51 @@
|
|||
1
|
||||
48
|
||||
AppCover.qml
|
||||
LoginSheet.qml
|
||||
main.qml
|
||||
49
|
||||
moment.js
|
||||
NewPostSheet.qml
|
||||
RefreshItem.qml
|
||||
SettingsPage.qml
|
||||
ThreadPage.qml
|
||||
PostItem.qml
|
||||
WebViewSheet.qml
|
||||
UserItem.qml
|
||||
UserPage.qml
|
||||
icons/at.png
|
||||
icons/bell-slash.png
|
||||
icons/bell.png
|
||||
icons/bookmark.png
|
||||
icons/messages.png
|
||||
icons/comments.png
|
||||
icons/default_cover.png
|
||||
icons/globe.png
|
||||
icons/home.png
|
||||
icons/ic_add.png
|
||||
icons/ic_add_bookmarks.png
|
||||
icons/ic_cancel.png
|
||||
icons/ic_compose.png
|
||||
icons/ic_contact.png
|
||||
icons/ic_del_bookmarks.png
|
||||
icons/ic_edit.png
|
||||
icons/ic_favorite.png
|
||||
icons/bell.png
|
||||
icons/minus-circle.png
|
||||
icons/ic_info.png
|
||||
icons/ic_reload.png
|
||||
icons/laughing_man.png
|
||||
icons/default_cover.png
|
||||
icons/star.png
|
||||
icons/ic_reply.png
|
||||
icons/ic_reply_all.png
|
||||
icons/ic_to_bottom.png
|
||||
icons/ic_to_top.png
|
||||
icons/laughing_man.png
|
||||
icons/messages.png
|
||||
icons/minus-circle.png
|
||||
icons/quote-left.png
|
||||
icons/refresh.png
|
||||
icons/retweet.png
|
||||
icons/sign-out.png
|
||||
icons/ic_doctype_picture.png
|
||||
icons/bookmark.png
|
||||
icons/star-o.png
|
||||
icons/star.png
|
||||
icons/ic_cancel.png
|
||||
icons/at.png
|
||||
icons/ic_reload.png
|
||||
icons/home.png
|
||||
icons/ic_copy.png
|
||||
icons/retweet.png
|
||||
icons/bell-slash.png
|
||||
icons/ic_favorite.png
|
||||
icons/ic_contact.png
|
||||
icons/refresh.png
|
||||
icons/quote-left.png
|
||||
icons/globe.png
|
||||
icons/ic_del_bookmarks.png
|
||||
icons/ic_add_bookmarks.png
|
||||
icons/ic_to_top.png
|
||||
icons/ic_edit.png
|
||||
icons/ic_compose.png
|
||||
icons/ic_to_bottom.png
|
||||
StreamTab.qml
|
||||
WebViewSheet.qml
|
||||
PostItem.qml
|
||||
ProfilePage.qml
|
||||
ThreadPage.qml
|
||||
parser.js
|
||||
AboutPage.qml
|
||||
LoginSheet.qml
|
||||
AppCover.qml
|
||||
SettingsPage.qml
|
||||
main.qml
|
||||
NewPostSheet.qml
|
||||
UserPage.qml
|
||||
|
|
|
@ -37,7 +37,7 @@ Page {
|
|||
horizontalAlignment: HorizontalAlignment.Center
|
||||
topPadding: ui.sdu(2)
|
||||
Label {
|
||||
text: "Copyright © 2016-2017 Morgan McMillian"
|
||||
text: "Copyright © 2016-2020 Morgan McMillian"
|
||||
textStyle.fontSize: FontSize.XSmall
|
||||
textFormat: TextFormat.Html
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ Page {
|
|||
horizontalAlignment: HorizontalAlignment.Center
|
||||
topPadding: ui.sdu(3)
|
||||
Label {
|
||||
text: "<a href=\"https://monkeystew.org\">https://monkeystew.org</a>"
|
||||
text: "<a href=\"https://thrrgilag.net\">https://thrrgilag.net</a>"
|
||||
textFormat: TextFormat.Html
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,10 @@ Sheet {
|
|||
property alias input: postText
|
||||
property alias text: postText.text
|
||||
property int count: 256
|
||||
property string counttext
|
||||
|
||||
signal sendPost(string text)
|
||||
signal postChanging(string text)
|
||||
|
||||
Page {
|
||||
titleBar: TitleBar {
|
||||
|
@ -56,20 +58,19 @@ Sheet {
|
|||
id: postText
|
||||
preferredHeight: 350.0
|
||||
onTextChanging: {
|
||||
postChanging(text)
|
||||
if (postText.text.length > 0) {
|
||||
sendAction.enabled = true;
|
||||
sendAction.enabled = true
|
||||
} else {
|
||||
sendAction.enabled = false;
|
||||
sendAction.enabled = false
|
||||
}
|
||||
count = 256 - postText.text.length
|
||||
if (count < 0) sendAction.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Container {
|
||||
horizontalAlignment: HorizontalAlignment.Right
|
||||
Label {
|
||||
text: count.toString()
|
||||
text: counttext
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import bb.cascades 1.4
|
||||
import org.labsquare 1.0
|
||||
import com.netimage 1.0
|
||||
import "moment.js" as Moment
|
||||
import "parser.js" as Parser
|
||||
|
||||
|
@ -36,24 +36,36 @@ Container {
|
|||
opacity: (ListItemData.is_deleted) ? 0.5 : 1.0
|
||||
visible: (ListItemData.is_deleted) ? false : true
|
||||
|
||||
Container {
|
||||
Container { // post header
|
||||
layout: DockLayout {}
|
||||
horizontalAlignment: HorizontalAlignment.Fill
|
||||
Container {
|
||||
layout: StackLayout {
|
||||
orientation: LayoutOrientation.LeftToRight
|
||||
}
|
||||
Container {
|
||||
Container { // user avatar
|
||||
background: (theme === VisualStyle.Bright) ? Color.create("#e9e9e9") : Color.create("#282828")
|
||||
WebImageView {
|
||||
ImageButton {
|
||||
id: avatar
|
||||
url: ListItemData.user.content.avatar_image.link
|
||||
minWidth: ui.du(12)
|
||||
minHeight: ui.du(12)
|
||||
maxWidth: ui.du(12)
|
||||
maxHeight: ui.du(12)
|
||||
//imageSource: "asset:///icons/laughing_man.png"
|
||||
defaultImage: tracker.image
|
||||
onClicked: {
|
||||
postitem.ListItem.view.viewProfile(ListItemData.user)
|
||||
}
|
||||
attachedObjects: [
|
||||
NetImageTracker {
|
||||
id: tracker
|
||||
source: (postitem.ListItem.view.hideAvatar()) ? "" : ListItemData.user.content.avatar_image.link
|
||||
manager: postitem.ListItem.view.userImageManager
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Container {
|
||||
Container { // user name
|
||||
leftMargin: ui.sdu(3.0)
|
||||
Container {
|
||||
Label {
|
||||
|
@ -65,19 +77,19 @@ Container {
|
|||
Container {
|
||||
Label {
|
||||
id: username
|
||||
text: ListItemData.user.username
|
||||
// text: "<a href=\"#profile\">" + ListItemData.user.username + "</a>"
|
||||
// activeTextHandler: ActiveTextHandler {
|
||||
// onTriggered: {
|
||||
// postitem.ListItem.view.viewProfile(ListItemData.user)
|
||||
// }
|
||||
// }
|
||||
// textFormat: TextFormat.Html
|
||||
// text: ListItemData.user.username
|
||||
text: "<a href=\"#profile\">" + ListItemData.user.username + "</a>"
|
||||
activeTextHandler: ActiveTextHandler {
|
||||
onTriggered: {
|
||||
postitem.ListItem.view.viewProfile(ListItemData.user)
|
||||
}
|
||||
}
|
||||
textFormat: TextFormat.Html
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Container {
|
||||
Container { // post counts
|
||||
horizontalAlignment: HorizontalAlignment.Right
|
||||
Container {
|
||||
layout: StackLayout {
|
||||
|
@ -133,35 +145,107 @@ Container {
|
|||
}
|
||||
}
|
||||
}
|
||||
Container {
|
||||
Container { // post text
|
||||
topMargin: ui.sdu(2.0)
|
||||
bottomMargin: ui.sdu(2.0)
|
||||
Label {
|
||||
text: Parser.parsePostData(ListItemData.content.html)
|
||||
text: Parser.fixPostHtml(ListItemData.content.html)
|
||||
multiline: true
|
||||
textFormat: TextFormat.Html
|
||||
navigation.focusPolicy: NavigationFocusPolicy.NotFocusable
|
||||
}
|
||||
}
|
||||
Container {
|
||||
Container { // long post body
|
||||
topMargin: ui.sdu(2.0)
|
||||
bottomMargin: ui.sdu(2.0)
|
||||
visible: {
|
||||
if (postitem.ListItem.view.hideLongPosts()) {
|
||||
return false
|
||||
} else {
|
||||
if (typeof ListItemData.longpost_body !== "undefined") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Divider {
|
||||
}
|
||||
Label {
|
||||
text: (typeof ListItemData.longpost_body !== "undefined") ? ListItemData.longpost_body : ""
|
||||
multiline: true
|
||||
textFormat: TextFormat.Html
|
||||
navigation.focusPolicy: NavigationFocusPolicy.NotFocusable
|
||||
}
|
||||
}
|
||||
Container { // post embeds
|
||||
// TODO: add tab to open full image in a page
|
||||
horizontalAlignment: HorizontalAlignment.Center
|
||||
bottomMargin: ui.sdu(2.0)
|
||||
WebImageView {
|
||||
url: {
|
||||
var oembed = ""
|
||||
ImageButton {
|
||||
id: pimage
|
||||
maxWidth: ui.du(20)
|
||||
maxHeight: ui.du(20)
|
||||
visible: {
|
||||
var isphoto = false
|
||||
if (typeof ListItemData.raw !== "undefined") {
|
||||
ListItemData.raw.forEach(function (item) {
|
||||
if (item["type"] == "io.pnut.core.oembed") {
|
||||
oembed = item["value"]["url"]
|
||||
if (item["value"]["type"] == "photo") {
|
||||
isphoto = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return oembed
|
||||
return isphoto
|
||||
}
|
||||
scalingMethod: ScalingMethod.AspectFit
|
||||
defaultImage: (postitem.ListItem.view.hidePhoto()) ? "" : thumbtracker.image
|
||||
onClicked: {
|
||||
postitem.ListItem.view.showImage(ptracker.imageSource)
|
||||
}
|
||||
attachedObjects: [
|
||||
NetImageTracker {
|
||||
id: ptracker
|
||||
manager: postitem.ListItem.view.listImageManager
|
||||
source: {
|
||||
var photo_url = ""
|
||||
if (typeof ListItemData.raw !== "undefined" && !postitem.ListItem.view.hidePhoto()) {
|
||||
ListItemData.raw.forEach(function (item) {
|
||||
if (item["type"] == "io.pnut.core.oembed") {
|
||||
if (item["value"]["type"] == "photo") {
|
||||
photo_url = item["value"]["url"]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return photo_url
|
||||
}
|
||||
},
|
||||
NetImageTracker {
|
||||
id: thumbtracker
|
||||
manager: postitem.ListItem.view.listImageManager
|
||||
source: {
|
||||
var photo_url = ""
|
||||
if (typeof ListItemData.raw !== "undefined" && !postitem.ListItem.view.hidePhoto()) {
|
||||
ListItemData.raw.forEach(function (item) {
|
||||
if (item["type"] == "io.pnut.core.oembed") {
|
||||
if (item["value"]["type"] == "photo") {
|
||||
if (item["value"]["thumbnail_url"]) {
|
||||
photo_url = item["value"]["thumbnail_url"]
|
||||
} else {
|
||||
photo_url = item["value"]["url"]
|
||||
}
|
||||
// photo_url = item["value"]["url"]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return photo_url
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Container {
|
||||
Container { // post footer
|
||||
layout: DockLayout {}
|
||||
horizontalAlignment: HorizontalAlignment.Fill
|
||||
Container {
|
||||
|
@ -174,8 +258,15 @@ Container {
|
|||
Container {
|
||||
horizontalAlignment: HorizontalAlignment.Right
|
||||
Label { // "Broadsword Hack"
|
||||
text: ListItemData.source.name
|
||||
text: {
|
||||
if (ListItemData.reposted_by) {
|
||||
return "reposted by @" + ListItemData.reposted_by
|
||||
} else {
|
||||
return ListItemData.source.name
|
||||
}
|
||||
}
|
||||
textStyle.fontSize: FontSize.XSmall
|
||||
textStyle.fontStyle: FontStyle.Italic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +279,7 @@ Container {
|
|||
ActionItem {
|
||||
title: qsTr("Reply")
|
||||
onTriggered: {
|
||||
replySheet.text = "@" + ListItemData.user.username + " ";
|
||||
replySheet.text = atMention(ListItemData.user.username);
|
||||
replySheet.open();
|
||||
replySheet.input.requestFocus();
|
||||
}
|
||||
|
@ -197,7 +288,7 @@ Container {
|
|||
ActionItem {
|
||||
title: qsTr("Reply All")
|
||||
onTriggered: {
|
||||
replySheet.text = "@" + ListItemData.user.username + " " + parseMentions(ListItemData.content.entities.mentions);
|
||||
replySheet.text = atMention(ListItemData.user.username) + parseMentions(ListItemData.content.entities.mentions);
|
||||
console.log(JSON.stringify(ListItemData.content.entities.mentions))
|
||||
replySheet.open();
|
||||
replySheet.input.requestFocus();
|
||||
|
@ -286,15 +377,21 @@ Container {
|
|||
onSendPost: {
|
||||
postitem.ListItem.view.sendReply(text, ListItemData.id);
|
||||
}
|
||||
onPostChanging: {
|
||||
replySheet.count = 256 - postitem.ListItem.view.postLength(text)
|
||||
if (replySheet.count < 0) {
|
||||
replySheet.counttext = "longpost"
|
||||
} else {
|
||||
replySheet.counttext = replySheet.count.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
function parseMentions(mentions) {
|
||||
var mtext = ""
|
||||
for(var i = 0; i < mentions.length; i++) {
|
||||
var mu = mentions[i].text
|
||||
if (mu !== postitem.ListItem.view.getUserName()) {
|
||||
mtext += "@" + mu + " "
|
||||
}
|
||||
mtext += atMention(mu)
|
||||
}
|
||||
if (mtext.length > 0) {
|
||||
if (postitem.ListItem.view.ccOnReply()) {
|
||||
|
@ -306,4 +403,11 @@ Container {
|
|||
return ""
|
||||
}
|
||||
}
|
||||
function atMention(username) {
|
||||
var atname = ""
|
||||
if (username !== postitem.ListItem.view.getUserName()) {
|
||||
atname = "@" + username + " "
|
||||
}
|
||||
return atname
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
*/
|
||||
|
||||
import bb.cascades 1.4
|
||||
import org.labsquare 1.0
|
||||
import com.netimage 1.0
|
||||
import "parser.js" as Parser
|
||||
|
||||
Page {
|
||||
|
||||
property variant imgManager: imgManager
|
||||
property variant user
|
||||
property variant theme: Application.themeSupport.theme.colorTheme.style
|
||||
property string lorem: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non enim tellus. Donec vestibulum enim urna, eget faucibus diam commodo a. Donec eget hendrerit metus. Pellentesque vehicula nisi nec vehicula ullamcorper. Aliquam a elit eget mi fringilla porta fermentum eget eros. Phasellus vestibulum nulla sed elit congue adipiscing. Cras imperdiet urna ac ipsum volutpat lobortis. Maecenas vehicula tortor at viverra convallis. Curabitur nibh massa, tristique id felis ut, venenatis faucibus dui. Donec fringilla, mi nec tincidunt dignissim, neque nunc semper mi, quis rutrum diam turpis sit amet erat. Cras a sodales nisi. Nunc sit amet diam sed lectus molestie cursus convallis et erat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis vitae varius leo. Mauris eu leo a nunc bibendum rutrum euismod et ipsum. "
|
||||
|
@ -45,13 +46,21 @@ Page {
|
|||
Container {
|
||||
Container {
|
||||
opacity: 0.6
|
||||
WebImageView {
|
||||
ImageView {
|
||||
id: cover
|
||||
preferredWidth: 1440
|
||||
maxHeight: ui.du(24)
|
||||
scalingMethod: ScalingMethod.AspectFill
|
||||
//imageSource: "asset:///icons/default_cover.png"
|
||||
url: user.content.cover_image.link
|
||||
//url: user.content.cover_image.link
|
||||
image: cimgtracker.image
|
||||
attachedObjects: [
|
||||
NetImageTracker {
|
||||
id: cimgtracker
|
||||
manager: imgManager
|
||||
source: user.content.cover_image.link
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,11 +73,19 @@ Page {
|
|||
verticalAlignment: VerticalAlignment.Center
|
||||
Container {
|
||||
background: (theme === VisualStyle.Bright) ? Color.create("#e9e9e9") : Color.create("#282828")
|
||||
WebImageView {
|
||||
ImageView {
|
||||
//imageSource: "asset:///icons/laughing_man.png"
|
||||
url: user.content.avatar_image.link
|
||||
//url: user.content.avatar_image.link
|
||||
maxHeight: ui.du(14)
|
||||
maxWidth: ui.du(14)
|
||||
image: aimgtracker.image
|
||||
attachedObjects: [
|
||||
NetImageTracker {
|
||||
id: aimgtracker
|
||||
manager: imgManager
|
||||
source: user.content.avatar_image.link
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Container {
|
||||
|
@ -110,7 +127,7 @@ Page {
|
|||
preferredWidth: ui.du(45)
|
||||
Label {
|
||||
//text: lorem
|
||||
text: Parser.parsePostData(user.content.html)
|
||||
text: Parser.parsePostText(user.content)
|
||||
multiline: true
|
||||
textFormat: TextFormat.Html
|
||||
}
|
||||
|
@ -278,6 +295,11 @@ Page {
|
|||
ComponentDefinition {
|
||||
id: userListPage
|
||||
source: "UserPage.qml"
|
||||
},
|
||||
NetImageManager {
|
||||
id: imgManager
|
||||
cacheId: "feedImageManager"
|
||||
cacheSize: 250
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ Page {
|
|||
Container {
|
||||
topPadding: ui.sdu(2)
|
||||
}
|
||||
Container {
|
||||
Container { // Unified home
|
||||
layout: DockLayout {}
|
||||
horizontalAlignment: HorizontalAlignment.Fill
|
||||
verticalAlignment: VerticalAlignment.Fill
|
||||
|
@ -71,7 +71,7 @@ Page {
|
|||
}
|
||||
}
|
||||
Divider {}
|
||||
Container {
|
||||
Container { // CC setting
|
||||
layout: DockLayout {}
|
||||
horizontalAlignment: HorizontalAlignment.Fill
|
||||
verticalAlignment: VerticalAlignment.Fill
|
||||
|
@ -110,7 +110,124 @@ Page {
|
|||
}
|
||||
}
|
||||
Divider {}
|
||||
Container {
|
||||
Container { // Hide photos setting
|
||||
layout: DockLayout {}
|
||||
horizontalAlignment: HorizontalAlignment.Fill
|
||||
verticalAlignment: VerticalAlignment.Fill
|
||||
Container {
|
||||
verticalAlignment: VerticalAlignment.Center
|
||||
leftPadding: ui.sdu(3)
|
||||
Label {
|
||||
text: qsTr("Hide photos")
|
||||
textStyle.fontSize: FontSize.Medium
|
||||
textStyle.fontWeight: FontWeight.Bold
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Hide embeded photos in timeline")
|
||||
textStyle.fontSize: FontSize.Small
|
||||
multiline: true
|
||||
}
|
||||
}
|
||||
Container {
|
||||
id: imgtoggle
|
||||
rightPadding: ui.sdu(3)
|
||||
horizontalAlignment: HorizontalAlignment.Right
|
||||
verticalAlignment: VerticalAlignment.Center
|
||||
ToggleButton {
|
||||
checked: _app.setting("hidephoto")
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
_app.setSetting("hidephoto", true)
|
||||
reload()
|
||||
} else {
|
||||
_app.setSetting("hidephoto", false)
|
||||
reload()
|
||||
}
|
||||
}
|
||||
accessibility.name: "inlineimages"
|
||||
}
|
||||
}
|
||||
}
|
||||
Divider {}
|
||||
Container { // Hide avatar setting
|
||||
layout: DockLayout {}
|
||||
horizontalAlignment: HorizontalAlignment.Fill
|
||||
verticalAlignment: VerticalAlignment.Fill
|
||||
Container {
|
||||
verticalAlignment: VerticalAlignment.Center
|
||||
leftPadding: ui.sdu(3)
|
||||
Label {
|
||||
text: qsTr("Hide avatars")
|
||||
textStyle.fontSize: FontSize.Medium
|
||||
textStyle.fontWeight: FontWeight.Bold
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Hide avatar images in timeline")
|
||||
textStyle.fontSize: FontSize.Small
|
||||
multiline: true
|
||||
}
|
||||
}
|
||||
Container {
|
||||
id: avatartoggle
|
||||
rightPadding: ui.sdu(3)
|
||||
horizontalAlignment: HorizontalAlignment.Right
|
||||
verticalAlignment: VerticalAlignment.Center
|
||||
ToggleButton {
|
||||
checked: _app.setting("hideavatar")
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
_app.setSetting("hideavatar", true)
|
||||
reload()
|
||||
} else {
|
||||
_app.setSetting("hideavatar", false)
|
||||
reload()
|
||||
}
|
||||
}
|
||||
accessibility.name: "avatars"
|
||||
}
|
||||
}
|
||||
}
|
||||
Divider {}
|
||||
Container { // Hide longposts setting
|
||||
layout: DockLayout {}
|
||||
horizontalAlignment: HorizontalAlignment.Fill
|
||||
verticalAlignment: VerticalAlignment.Fill
|
||||
Container {
|
||||
verticalAlignment: VerticalAlignment.Center
|
||||
leftPadding: ui.sdu(3)
|
||||
Label {
|
||||
text: qsTr("Hide long posts")
|
||||
textStyle.fontSize: FontSize.Medium
|
||||
textStyle.fontWeight: FontWeight.Bold
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Hide long posts in timeline")
|
||||
textStyle.fontSize: FontSize.Small
|
||||
multiline: true
|
||||
}
|
||||
}
|
||||
Container {
|
||||
id: longposttoggle
|
||||
rightPadding: ui.sdu(3)
|
||||
horizontalAlignment: HorizontalAlignment.Right
|
||||
verticalAlignment: VerticalAlignment.Center
|
||||
ToggleButton {
|
||||
checked: _app.setting("hidelongp")
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
_app.setSetting("hidelongp", true)
|
||||
reload()
|
||||
} else {
|
||||
_app.setSetting("hidelongp", false)
|
||||
reload()
|
||||
}
|
||||
}
|
||||
accessibility.name: "longposts"
|
||||
}
|
||||
}
|
||||
}
|
||||
Divider {}
|
||||
Container { // Theme Setting
|
||||
leftPadding: ui.sdu(3)
|
||||
rightPadding: ui.sdu(3)
|
||||
DropDown {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
import bb.cascades 1.4
|
||||
import com.monkeystew.pnut 1.0
|
||||
import com.monkeystew.qtimer 1.0
|
||||
import com.netimage 1.0
|
||||
|
||||
NavigationPane {
|
||||
id: nav
|
||||
|
@ -42,6 +43,9 @@ NavigationPane {
|
|||
Container {
|
||||
ListView {
|
||||
id: streamView
|
||||
property variant listImageManager: feedImageManager
|
||||
property variant userImageManager: userImageManager
|
||||
property bool fetching: false
|
||||
dataModel: ArrayDataModel {
|
||||
id: postModel
|
||||
}
|
||||
|
@ -86,7 +90,7 @@ NavigationPane {
|
|||
nav.push(page);
|
||||
}
|
||||
function sendReply(text, pid) {
|
||||
pnut.sendReply(text, pid);
|
||||
pnut.sendPost(text, pid);
|
||||
}
|
||||
function getUserName() {
|
||||
return _app.setting("username");
|
||||
|
@ -109,6 +113,9 @@ NavigationPane {
|
|||
function getPost(pid) {
|
||||
pnut.getPost(pid)
|
||||
}
|
||||
function postLength(text) {
|
||||
return pnut.postLength(text)
|
||||
}
|
||||
function ccOnReply() {
|
||||
if (_app.setting("cc") === "true") {
|
||||
return true
|
||||
|
@ -116,14 +123,40 @@ NavigationPane {
|
|||
return false
|
||||
}
|
||||
}
|
||||
function hidePhoto() {
|
||||
if (_app.setting("hidephoto") === "true") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function hideAvatar() {
|
||||
if (_app.setting("hideavatar") === "true") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function hideLongPosts() {
|
||||
if (_app.setting("hidelongp") === "true") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function copyText(text) {
|
||||
_app.copyText(text)
|
||||
}
|
||||
function showImage(filename) {
|
||||
_app.showImage(filename)
|
||||
}
|
||||
attachedObjects: [
|
||||
ListScrollStateHandler {
|
||||
onAtEndChanged: {
|
||||
streamView.fetching = false
|
||||
if (atEnd) {
|
||||
if (!at_end && pnut.beforeId != 0) {
|
||||
if (!streamView.fetching && pnut.beforeId != 0) {
|
||||
streamView.fetching = true
|
||||
pnut.getStream(endpoint, Pnut.STREAM_OLDER);
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +167,15 @@ NavigationPane {
|
|||
nav.parent.unreadContentCount = unread
|
||||
}
|
||||
}
|
||||
},
|
||||
NetImageManager {
|
||||
id: feedImageManager
|
||||
cacheId: "feedImageManager"
|
||||
cacheSize: 250
|
||||
},
|
||||
NetImageManager {
|
||||
id: userImageManager
|
||||
cacheId: "userImageManager"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -212,7 +254,15 @@ NavigationPane {
|
|||
id: newPostSheet
|
||||
onSendPost: {
|
||||
console.log("send: " + text)
|
||||
pnut.sendPost(text)
|
||||
pnut.sendPost(text, 0)
|
||||
}
|
||||
onPostChanging: {
|
||||
newPostSheet.count = 256 - pnut.postLength(text)
|
||||
if (newPostSheet.count < 0) {
|
||||
newPostSheet.counttext = "longpost"
|
||||
} else {
|
||||
newPostSheet.counttext = newPostSheet.count.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
WebViewSheet {
|
||||
|
@ -356,6 +406,7 @@ NavigationPane {
|
|||
pnut.authorize()
|
||||
}
|
||||
function logout() {
|
||||
postModel.clear()
|
||||
pnut.logout()
|
||||
}
|
||||
function reload() {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import bb.cascades 1.4
|
||||
import com.netimage 1.0
|
||||
|
||||
Page {
|
||||
|
||||
|
@ -31,6 +32,8 @@ Page {
|
|||
Container {
|
||||
ListView {
|
||||
id: threadView
|
||||
property variant listImageManager: feedImageManager
|
||||
property variant userImageManager: userImageManager
|
||||
dataModel: ArrayDataModel {
|
||||
id: threadModel
|
||||
}
|
||||
|
@ -41,7 +44,7 @@ Page {
|
|||
}
|
||||
]
|
||||
function sendReply(text, pid) {
|
||||
pnut.sendReply(text, pid);
|
||||
pnut.sendPost(text, pid);
|
||||
}
|
||||
function getUserName() {
|
||||
return _app.setting("username")
|
||||
|
@ -64,6 +67,41 @@ Page {
|
|||
return false
|
||||
}
|
||||
}
|
||||
function hidePhoto() {
|
||||
if (_app.setting("hidephoto") === "true") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function hideAvatar() {
|
||||
if (_app.setting("hideavatar") === "true") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function hideLongPosts() {
|
||||
if (_app.setting("hidelongp") === "true") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function showImage(filename) {
|
||||
_app.showImage(filename)
|
||||
}
|
||||
attachedObjects: [
|
||||
NetImageManager {
|
||||
id: feedImageManager
|
||||
cacheId: "feedImageManager"
|
||||
cacheSize: 250
|
||||
},
|
||||
NetImageManager {
|
||||
id: userImageManager
|
||||
cacheId: "userImageManager"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import bb.cascades 1.4
|
||||
import org.labsquare 1.0
|
||||
import com.netimage 1.0
|
||||
import "parser.js" as Parser
|
||||
|
||||
Container {
|
||||
id: useritem
|
||||
|
@ -20,12 +21,25 @@ Container {
|
|||
Container {
|
||||
minWidth: ui.du(12)
|
||||
background: (theme === VisualStyle.Bright) ? Color.create("#e9e9e9") : Color.create("#282828")
|
||||
WebImageView {
|
||||
ImageView {
|
||||
id: avatar
|
||||
url: ListItemData.content.avatar_image.link
|
||||
//url: ListItemData.content.avatar_image.link
|
||||
maxWidth: ui.du(12)
|
||||
maxHeight: ui.du(12)
|
||||
//imageSource: "asset:///icons/laughing_man.png"
|
||||
image: aimgtracker.image
|
||||
attachedObjects: [
|
||||
NetImageTracker {
|
||||
id: aimgtracker
|
||||
manager: imgManager
|
||||
source: ListItemData.content.avatar_image.link
|
||||
},
|
||||
NetImageManager {
|
||||
id: imgManager
|
||||
cacheId: "feedImageManager"
|
||||
cacheSize: 250
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Container {
|
||||
|
@ -41,7 +55,7 @@ Container {
|
|||
Container {
|
||||
Label {
|
||||
id: description
|
||||
text: ListItemData.content.html
|
||||
text: Parser.fixPostHtml(ListItemData.content.html)
|
||||
multiline: true
|
||||
textFormat: TextFormat.Html
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import bb.cascades 1.4
|
|||
Sheet {
|
||||
peekEnabled: false
|
||||
property alias url: webview.url
|
||||
property bool authredir: true
|
||||
Page {
|
||||
ScrollView {
|
||||
scrollViewProperties.pinchToZoomEnabled: true
|
||||
|
@ -12,12 +13,15 @@ Sheet {
|
|||
settings.zoomToFitEnabled: true
|
||||
|
||||
onUrlChanged: {
|
||||
//console.log("::" + url)
|
||||
// console.log("::" + url)
|
||||
// Workaround for 10.3.3
|
||||
if (url.toString().match(/http\:\/\/.*#access_token\=/i)) {
|
||||
//console.log("Matched url: " + url.toString());
|
||||
webview.stop();
|
||||
webview.url = url.toString();
|
||||
if (authredir === true) {
|
||||
if (url.toString().match(/http\:\/\/.*#access_token\=/i)) {
|
||||
// console.log("Matched url: " + url.toString());
|
||||
webview.stop();
|
||||
webview.url = url.toString();
|
||||
authredir = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
BIN
assets/icons/ic_doctype_picture.png
Normal file
BIN
assets/icons/ic_doctype_picture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -58,6 +58,12 @@ TabbedPane {
|
|||
case "HomeTab":
|
||||
return homeStream
|
||||
break;
|
||||
case "MentionTab":
|
||||
return mentionStream
|
||||
break;
|
||||
case "BookmarksTab":
|
||||
return bookmarksStream
|
||||
break;
|
||||
default:
|
||||
return globalStream
|
||||
}
|
||||
|
|
356
assets/parser.js
356
assets/parser.js
|
@ -17,348 +17,14 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function parsePostData(t) {
|
||||
t = t.replace(/!/g,"\u0021");
|
||||
t = t.replace(/"/g,"\u0022");
|
||||
t = t.replace(/#/g,"\u0023");
|
||||
t = t.replace(/$/g,"\u0024");
|
||||
t = t.replace(/%/g,"\u0025");
|
||||
t = t.replace(/&/g,"\u0026");
|
||||
t = t.replace(/'/g,"\u0027");
|
||||
t = t.replace(/(/g,"\u0028");
|
||||
t = t.replace(/)/g,"\u0029");
|
||||
t = t.replace(/*/g,"\u002A");
|
||||
t = t.replace(/+/g,"\u002B");
|
||||
t = t.replace(/,/g,"\u002C");
|
||||
t = t.replace(/-/g,"\u002D");
|
||||
t = t.replace(/./g,"\u002E");
|
||||
t = t.replace(///g,"\u002F");
|
||||
t = t.replace(/0/g,"\u0030");
|
||||
t = t.replace(/1/g,"\u0031");
|
||||
t = t.replace(/2/g,"\u0032");
|
||||
t = t.replace(/3/g,"\u0033");
|
||||
t = t.replace(/4/g,"\u0034");
|
||||
t = t.replace(/5/g,"\u0035");
|
||||
t = t.replace(/6/g,"\u0036");
|
||||
t = t.replace(/7/g,"\u0037");
|
||||
t = t.replace(/8/g,"\u0038");
|
||||
t = t.replace(/9/g,"\u0039");
|
||||
t = t.replace(/:/g,"\u003A");
|
||||
t = t.replace(/;/g,"\u003B");
|
||||
t = t.replace(/</g,"\u003C");
|
||||
t = t.replace(/=/g,"\u003D");
|
||||
t = t.replace(/>/g,"\u003E");
|
||||
t = t.replace(/?/g,"\u003F");
|
||||
t = t.replace(/@/g,"\u0040");
|
||||
t = t.replace(/A/g,"\u0041");
|
||||
t = t.replace(/B/g,"\u0042");
|
||||
t = t.replace(/C/g,"\u0043");
|
||||
t = t.replace(/D/g,"\u0044");
|
||||
t = t.replace(/E/g,"\u0045");
|
||||
t = t.replace(/F/g,"\u0046");
|
||||
t = t.replace(/G/g,"\u0047");
|
||||
t = t.replace(/H/g,"\u0048");
|
||||
t = t.replace(/I/g,"\u0049");
|
||||
t = t.replace(/J/g,"\u004A");
|
||||
t = t.replace(/K/g,"\u004B");
|
||||
t = t.replace(/L/g,"\u004C");
|
||||
t = t.replace(/M/g,"\u004D");
|
||||
t = t.replace(/N/g,"\u004E");
|
||||
t = t.replace(/O/g,"\u004F");
|
||||
t = t.replace(/P/g,"\u0050");
|
||||
t = t.replace(/Q/g,"\u0051");
|
||||
t = t.replace(/R/g,"\u0052");
|
||||
t = t.replace(/S/g,"\u0053");
|
||||
t = t.replace(/T/g,"\u0054");
|
||||
t = t.replace(/U/g,"\u0055");
|
||||
t = t.replace(/V/g,"\u0056");
|
||||
t = t.replace(/W/g,"\u0057");
|
||||
t = t.replace(/X/g,"\u0058");
|
||||
t = t.replace(/Y/g,"\u0059");
|
||||
t = t.replace(/Z/g,"\u005A");
|
||||
t = t.replace(/[/g,"\u005B");
|
||||
t = t.replace(/\/g,"\u005C");
|
||||
t = t.replace(/]/g,"\u005D");
|
||||
t = t.replace(/^/g,"\u005E");
|
||||
t = t.replace(/_/g,"\u005F");
|
||||
t = t.replace(/`/g,"\u0060");
|
||||
t = t.replace(/a/g,"\u0061");
|
||||
t = t.replace(/b/g,"\u0062");
|
||||
t = t.replace(/c/g,"\u0063");
|
||||
t = t.replace(/d/g,"\u0064");
|
||||
t = t.replace(/e/g,"\u0065");
|
||||
t = t.replace(/f/g,"\u0066");
|
||||
t = t.replace(/g/g,"\u0067");
|
||||
t = t.replace(/h/g,"\u0068");
|
||||
t = t.replace(/i/g,"\u0069");
|
||||
t = t.replace(/j/g,"\u006A");
|
||||
t = t.replace(/k/g,"\u006B");
|
||||
t = t.replace(/l/g,"\u006C");
|
||||
t = t.replace(/m/g,"\u006D");
|
||||
t = t.replace(/n/g,"\u006E");
|
||||
t = t.replace(/o/g,"\u006F");
|
||||
t = t.replace(/p/g,"\u0070");
|
||||
t = t.replace(/q/g,"\u0071");
|
||||
t = t.replace(/r/g,"\u0072");
|
||||
t = t.replace(/s/g,"\u0073");
|
||||
t = t.replace(/t/g,"\u0074");
|
||||
t = t.replace(/u/g,"\u0075");
|
||||
t = t.replace(/v/g,"\u0076");
|
||||
t = t.replace(/w/g,"\u0077");
|
||||
t = t.replace(/x/g,"\u0078");
|
||||
t = t.replace(/y/g,"\u0079");
|
||||
t = t.replace(/z/g,"\u007A");
|
||||
t = t.replace(/{/g,"\u007B");
|
||||
t = t.replace(/|/g,"\u007C");
|
||||
t = t.replace(/}/g,"\u007D");
|
||||
t = t.replace(/~/g,"\u007E");
|
||||
t = t.replace(//g,"\u007F");
|
||||
t = t.replace(/€/g,"\u0080");
|
||||
t = t.replace(/‚/g,"\u0082");
|
||||
t = t.replace(/ƒ/g,"\u0083");
|
||||
t = t.replace(/„/g,"\u0084");
|
||||
t = t.replace(/…/g,"\u0085");
|
||||
t = t.replace(/†/g,"\u0086");
|
||||
t = t.replace(/‡/g,"\u0087");
|
||||
t = t.replace(/ˆ/g,"\u0088");
|
||||
t = t.replace(/‰/g,"\u0089");
|
||||
t = t.replace(/Š/g,"\u008A");
|
||||
t = t.replace(/‹/g,"\u008B");
|
||||
t = t.replace(/Œ/g,"\u008C");
|
||||
t = t.replace(//g,"\u008D");
|
||||
t = t.replace(/Ž/g,"\u008E");
|
||||
t = t.replace(/‘/g,"\u0091");
|
||||
t = t.replace(/’/g,"\u0092");
|
||||
t = t.replace(/“/g,"\u0093");
|
||||
t = t.replace(/”/g,"\u0094");
|
||||
t = t.replace(/•/g,"\u0095");
|
||||
t = t.replace(/–/g,"\u0096");
|
||||
t = t.replace(/—/g,"\u0097");
|
||||
t = t.replace(/˜/g,"\u0098");
|
||||
t = t.replace(/™/g,"\u0099");
|
||||
t = t.replace(/š/g,"\u009A");
|
||||
t = t.replace(/›/g,"\u009B");
|
||||
t = t.replace(/œ/g,"\u009C");
|
||||
t = t.replace(/ž/g,"\u009E");
|
||||
t = t.replace(/Ÿ/g,"\u009F");
|
||||
t = t.replace(/¡/g,"\u00A1");
|
||||
t = t.replace(/¢/g,"\u00A2");
|
||||
t = t.replace(/£/g,"\u00A3");
|
||||
t = t.replace(/¤/g,"\u00A4");
|
||||
t = t.replace(/¥/g,"\u00A5");
|
||||
t = t.replace(/¦/g,"\u00A6");
|
||||
t = t.replace(/§/g,"\u00A7");
|
||||
t = t.replace(/¨/g,"\u00A8");
|
||||
t = t.replace(/©/g,"\u00A9");
|
||||
t = t.replace(/ª/g,"\u00AA");
|
||||
t = t.replace(/«/g,"\u00AB");
|
||||
t = t.replace(/¬/g,"\u00AC");
|
||||
t = t.replace(/®/g,"\u00AE");
|
||||
t = t.replace(/¯/g,"\u00AF");
|
||||
t = t.replace(/°/g,"\u00B0");
|
||||
t = t.replace(/±/g,"\u00B1");
|
||||
t = t.replace(/²/g,"\u00B2");
|
||||
t = t.replace(/³/g,"\u00B3");
|
||||
t = t.replace(/´/g,"\u00B4");
|
||||
t = t.replace(/µ/g,"\u00B5");
|
||||
t = t.replace(/¶/g,"\u00B6");
|
||||
t = t.replace(/·/g,"\u00B7");
|
||||
t = t.replace(/¸/g,"\u00B8");
|
||||
t = t.replace(/¹/g,"\u00B9");
|
||||
t = t.replace(/º/g,"\u00BA");
|
||||
t = t.replace(/»/g,"\u00BB");
|
||||
t = t.replace(/¼/g,"\u00BC");
|
||||
t = t.replace(/½/g,"\u00BD");
|
||||
t = t.replace(/¾/g,"\u00BE");
|
||||
t = t.replace(/¿/g,"\u00BF");
|
||||
t = t.replace(/À/g,"\u00C0");
|
||||
t = t.replace(/Á/g,"\u00C1");
|
||||
t = t.replace(/Â/g,"\u00C2");
|
||||
t = t.replace(/Ã/g,"\u00C3");
|
||||
t = t.replace(/Ä/g,"\u00C4");
|
||||
t = t.replace(/Å/g,"\u00C5");
|
||||
t = t.replace(/Æ/g,"\u00C6");
|
||||
t = t.replace(/Ç/g,"\u00C7");
|
||||
t = t.replace(/È/g,"\u00C8");
|
||||
t = t.replace(/É/g,"\u00C9");
|
||||
t = t.replace(/Ê/g,"\u00CA");
|
||||
t = t.replace(/Ë/g,"\u00CB");
|
||||
t = t.replace(/Ì/g,"\u00CC");
|
||||
t = t.replace(/Í/g,"\u00CD");
|
||||
t = t.replace(/Î/g,"\u00CE");
|
||||
t = t.replace(/Ï/g,"\u00CF");
|
||||
t = t.replace(/Ð/g,"\u00D0");
|
||||
t = t.replace(/Ñ/g,"\u00D1");
|
||||
t = t.replace(/Ò/g,"\u00D2");
|
||||
t = t.replace(/Ó/g,"\u00D3");
|
||||
t = t.replace(/Ô/g,"\u00D4");
|
||||
t = t.replace(/Õ/g,"\u00D5");
|
||||
t = t.replace(/Ö/g,"\u00D6");
|
||||
t = t.replace(/×/g,"\u00D7");
|
||||
t = t.replace(/Ø/g,"\u00D8");
|
||||
t = t.replace(/Ù/g,"\u00D9");
|
||||
t = t.replace(/Ú/g,"\u00DA");
|
||||
t = t.replace(/Û/g,"\u00DB");
|
||||
t = t.replace(/Ü/g,"\u00DC");
|
||||
t = t.replace(/Ý/g,"\u00DD");
|
||||
t = t.replace(/Þ/g,"\u00DE");
|
||||
t = t.replace(/ß/g,"\u00DF");
|
||||
t = t.replace(/à/g,"\u00E0");
|
||||
t = t.replace(/á/g,"\u00E1");
|
||||
t = t.replace(/â/g,"\u00E2");
|
||||
t = t.replace(/ã/g,"\u00E3");
|
||||
t = t.replace(/ä/g,"\u00E4");
|
||||
t = t.replace(/å/g,"\u00E5");
|
||||
t = t.replace(/æ/g,"\u00E6");
|
||||
t = t.replace(/ç/g,"\u00E7");
|
||||
t = t.replace(/è/g,"\u00E8");
|
||||
t = t.replace(/é/g,"\u00E9");
|
||||
t = t.replace(/ê/g,"\u00EA");
|
||||
t = t.replace(/ë/g,"\u00EB");
|
||||
t = t.replace(/ì/g,"\u00EC");
|
||||
t = t.replace(/í/g,"\u00ED");
|
||||
t = t.replace(/î/g,"\u00EE");
|
||||
t = t.replace(/ï/g,"\u00EF");
|
||||
t = t.replace(/ð/g,"\u00F0");
|
||||
t = t.replace(/ñ/g,"\u00F1");
|
||||
t = t.replace(/ò/g,"\u00F2");
|
||||
t = t.replace(/ó/g,"\u00F3");
|
||||
t = t.replace(/ô/g,"\u00F4");
|
||||
t = t.replace(/õ/g,"\u00F5");
|
||||
t = t.replace(/ö/g,"\u00F6");
|
||||
t = t.replace(/÷/g,"\u00F7");
|
||||
t = t.replace(/ø/g,"\u00F8");
|
||||
t = t.replace(/ù/g,"\u00F9");
|
||||
t = t.replace(/ú/g,"\u00FA");
|
||||
t = t.replace(/û/g,"\u00FB");
|
||||
t = t.replace(/ü/g,"\u00FC");
|
||||
t = t.replace(/ý/g,"\u00FD");
|
||||
t = t.replace(/þ/g,"\u00FE");
|
||||
t = t.replace(/ÿ/g,"\u00FF");
|
||||
t = t.replace(/"/g,"\u0022");
|
||||
t = t.replace(/<3/g, "\u2764");
|
||||
t = t.replace(/</g,"\u02C2");
|
||||
t = t.replace(/>/g,"\u02C3");
|
||||
t = t.replace(/€/g,"\u0080");
|
||||
t = t.replace(/‚/g,"\u0082");
|
||||
t = t.replace(/ƒ/g,"\u0083");
|
||||
t = t.replace(/„/g,"\u0084");
|
||||
t = t.replace(/…/g,"\u0085");
|
||||
t = t.replace(/†/g,"\u0086");
|
||||
t = t.replace(/‡/g,"\u0087");
|
||||
t = t.replace(/ˆ/g,"\u0088");
|
||||
t = t.replace(/‰/g,"\u0089");
|
||||
t = t.replace(/Š/g,"\u008A");
|
||||
t = t.replace(/‹/g,"\u008B");
|
||||
t = t.replace(/Œ/g,"\u008C");
|
||||
t = t.replace(/‘/g,"\u0091");
|
||||
t = t.replace(/’/g,"\u0092");
|
||||
t = t.replace(/“/g,"\u0093");
|
||||
t = t.replace(/”/g,"\u0094");
|
||||
t = t.replace(/•/g,"\u0095");
|
||||
t = t.replace(/–/g,"\u0096");
|
||||
t = t.replace(/—/g,"\u0097");
|
||||
t = t.replace(/˜/g,"\u0098");
|
||||
t = t.replace(/™/g,"\u0099");
|
||||
t = t.replace(/š/g,"\u009A");
|
||||
t = t.replace(/›/g,"\u009B");
|
||||
t = t.replace(/œ/g,"\u009C");
|
||||
t = t.replace(/ÿ/g,"\u009F");
|
||||
t = t.replace(/¡/g,"\u00A1");
|
||||
t = t.replace(/¢/g,"\u00A2");
|
||||
t = t.replace(/£/g,"\u00A3");
|
||||
t = t.replace(/¤/g,"\u00A4");
|
||||
t = t.replace(/¥/g,"\u00A5");
|
||||
t = t.replace(/¦/g,"\u00A6");
|
||||
t = t.replace(/§/g,"\u00A7");
|
||||
t = t.replace(/¨/g,"\u00A8");
|
||||
t = t.replace(/©/g,"\u00A9");
|
||||
t = t.replace(/ª/g,"\u00AA");
|
||||
t = t.replace(/«/g,"\u00AB");
|
||||
t = t.replace(/¬/g,"\u00AC");
|
||||
t = t.replace(/®/g,"\u00AE");
|
||||
t = t.replace(/¯/g,"\u00AF");
|
||||
t = t.replace(/°/g,"\u00B0");
|
||||
t = t.replace(/±/g,"\u00B1");
|
||||
t = t.replace(/²/g,"\u00B2");
|
||||
t = t.replace(/³/g,"\u00B3");
|
||||
t = t.replace(/´/g,"\u00B4");
|
||||
t = t.replace(/µ/g,"\u00B5");
|
||||
t = t.replace(/¶/g,"\u00B6");
|
||||
t = t.replace(/·/g,"\u00B7");
|
||||
t = t.replace(/¸/g,"\u00B8");
|
||||
t = t.replace(/¹/g,"\u00B9");
|
||||
t = t.replace(/º/g,"\u00BA");
|
||||
t = t.replace(/»/g,"\u00BB");
|
||||
t = t.replace(/¼/g,"\u00BC");
|
||||
t = t.replace(/½/g,"\u00BD");
|
||||
t = t.replace(/¾/g,"\u00BE");
|
||||
t = t.replace(/¿/g,"\u00BF");
|
||||
t = t.replace(/À/g,"\u00C0");
|
||||
t = t.replace(/Á/g,"\u00C1");
|
||||
t = t.replace(/Â/g,"\u00C2");
|
||||
t = t.replace(/Ã/g,"\u00C3");
|
||||
t = t.replace(/Ä/g,"\u00C4");
|
||||
t = t.replace(/Å/g,"\u00C5");
|
||||
t = t.replace(/Æ/g,"\u00C6");
|
||||
t = t.replace(/Ç/g,"\u00C7");
|
||||
t = t.replace(/È/g,"\u00C8");
|
||||
t = t.replace(/É/g,"\u00C9");
|
||||
t = t.replace(/Ê/g,"\u00CA");
|
||||
t = t.replace(/Ë/g,"\u00CB");
|
||||
t = t.replace(/Ì/g,"\u00CC");
|
||||
t = t.replace(/Í/g,"\u00CD");
|
||||
t = t.replace(/Î/g,"\u00CE");
|
||||
t = t.replace(/Ï/g,"\u00CF");
|
||||
t = t.replace(/Ð/g,"\u00D0");
|
||||
t = t.replace(/Ñ/g,"\u00D1");
|
||||
t = t.replace(/Ò/g,"\u00D2");
|
||||
t = t.replace(/Ó/g,"\u00D3");
|
||||
t = t.replace(/Ô/g,"\u00D4");
|
||||
t = t.replace(/Õ/g,"\u00D5");
|
||||
t = t.replace(/Ö/g,"\u00D6");
|
||||
t = t.replace(/×/g,"\u00D7");
|
||||
t = t.replace(/Ø/g,"\u00D8");
|
||||
t = t.replace(/Ù/g,"\u00D9");
|
||||
t = t.replace(/Ú/g,"\u00DA");
|
||||
t = t.replace(/Û/g,"\u00DB");
|
||||
t = t.replace(/Ü/g,"\u00DC");
|
||||
t = t.replace(/Ý/g,"\u00DD");
|
||||
t = t.replace(/Þ/g,"\u00DE");
|
||||
t = t.replace(/ß/g,"\u00DF");
|
||||
t = t.replace(/à/g,"\u00E0");
|
||||
t = t.replace(/á/g,"\u00E1");
|
||||
t = t.replace(/â/g,"\u00E2");
|
||||
t = t.replace(/ã/g,"\u00E3");
|
||||
t = t.replace(/ä/g,"\u00E4");
|
||||
t = t.replace(/å/g,"\u00E5");
|
||||
t = t.replace(/æ/g,"\u00E6");
|
||||
t = t.replace(/ç/g,"\u00E7");
|
||||
t = t.replace(/è/g,"\u00E8");
|
||||
t = t.replace(/é/g,"\u00E9");
|
||||
t = t.replace(/ê/g,"\u00EA");
|
||||
t = t.replace(/ë/g,"\u00EB");
|
||||
t = t.replace(/ì/g,"\u00EC");
|
||||
t = t.replace(/í/g,"\u00ED");
|
||||
t = t.replace(/î/g,"\u00EE");
|
||||
t = t.replace(/ï/g,"\u00EF");
|
||||
t = t.replace(/ð/g,"\u00F0");
|
||||
t = t.replace(/ñ/g,"\u00F1");
|
||||
t = t.replace(/ò/g,"\u00F2");
|
||||
t = t.replace(/ó/g,"\u00F3");
|
||||
t = t.replace(/ô/g,"\u00F4");
|
||||
t = t.replace(/õ/g,"\u00F5");
|
||||
t = t.replace(/ö/g,"\u00F6");
|
||||
t = t.replace(/÷/g,"\u00F7");
|
||||
t = t.replace(/ø/g,"\u00F8");
|
||||
t = t.replace(/ù/g,"\u00F9");
|
||||
t = t.replace(/ú/g,"\u00FA");
|
||||
t = t.replace(/û/g,"\u00FB");
|
||||
t = t.replace(/ü/g,"\u00FC");
|
||||
t = t.replace(/ý/g,"\u00FD");
|
||||
t = t.replace(/þ/g,"\u00FE");
|
||||
t = t.replace(/ÿ/g,"\u00FF");
|
||||
t = t.replace(/<br>/g,"<br/>");
|
||||
t = t.replace(/(?!&)&/g, "&");
|
||||
return t;
|
||||
};
|
||||
function fixPostHtml(data) {
|
||||
data = data.replace(/<\\?\/?span[^>]*>/g, "");
|
||||
data = data.replace(/<br>/g, "<br/>");
|
||||
var hrefreg = /<a\shref=\\?"([^>]*)\\?">/;
|
||||
var hrefm = hrefreg.exec(data);
|
||||
if (hrefm != null) {
|
||||
var href = hrefm[1].replace(/&/g, "&");
|
||||
data = data.replace(hrefreg, "<a href=\"" + href + "\">");
|
||||
}
|
||||
return data;
|
||||
}
|
|
@ -46,6 +46,7 @@
|
|||
<configuration name="Simulator-Debug">
|
||||
<platformArchitecture>x86</platformArchitecture>
|
||||
<asset path="x86/o-g/Goober" entry="true" type="Qnx/Elf">Goober</asset>
|
||||
<asset path="../bb-cascades-oauth/oauth/o-g/libkqoauth.so" type="Qnx/Elf">lib/libkqoauth.so.1</asset>
|
||||
</configuration>
|
||||
|
||||
<!-- The name that is displayed in the BlackBerry 10 application installer.
|
||||
|
@ -55,7 +56,7 @@
|
|||
<!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade.
|
||||
Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
|
||||
An updated version of application must have a versionNumber value higher than the previous version. Required. -->
|
||||
<versionNumber>0.8.0</versionNumber>
|
||||
<versionNumber>0.9.5</versionNumber>
|
||||
|
||||
<!-- Fourth digit segment of the package version. First three segments are taken from the
|
||||
<versionNumber> element. Must be an integer from 0 to 2^16-1 -->
|
||||
|
|
16
config.pri
16
config.pri
|
@ -94,6 +94,7 @@ config_pri_assets {
|
|||
$$quote($$BASEDIR/assets/icons/ic_contact.png) \
|
||||
$$quote($$BASEDIR/assets/icons/ic_copy.png) \
|
||||
$$quote($$BASEDIR/assets/icons/ic_del_bookmarks.png) \
|
||||
$$quote($$BASEDIR/assets/icons/ic_doctype_picture.png) \
|
||||
$$quote($$BASEDIR/assets/icons/ic_edit.png) \
|
||||
$$quote($$BASEDIR/assets/icons/ic_favorite.png) \
|
||||
$$quote($$BASEDIR/assets/icons/ic_info.png) \
|
||||
|
@ -121,18 +122,22 @@ config_pri_source_group1 {
|
|||
$$quote($$BASEDIR/src/ActiveFrameQML.cpp) \
|
||||
$$quote($$BASEDIR/src/Pnut.cpp) \
|
||||
$$quote($$BASEDIR/src/Pnut_test.cpp) \
|
||||
$$quote($$BASEDIR/src/WebImageView.cpp) \
|
||||
$$quote($$BASEDIR/src/applicationui.cpp) \
|
||||
$$quote($$BASEDIR/src/main.cpp)
|
||||
$$quote($$BASEDIR/src/main.cpp) \
|
||||
$$quote($$BASEDIR/src/netimagemanager.cpp) \
|
||||
$$quote($$BASEDIR/src/netimagetracker.cpp)
|
||||
|
||||
HEADERS += \
|
||||
$$quote($$BASEDIR/src/ActiveFrameQML.h) \
|
||||
$$quote($$BASEDIR/src/Pnut.h) \
|
||||
$$quote($$BASEDIR/src/WebImageView.h) \
|
||||
$$quote($$BASEDIR/src/applicationui.hpp) \
|
||||
$$quote($$BASEDIR/src/globals.h)
|
||||
$$quote($$BASEDIR/src/globals.h) \
|
||||
$$quote($$BASEDIR/src/netimagemanager.h) \
|
||||
$$quote($$BASEDIR/src/netimagetracker.h)
|
||||
}
|
||||
|
||||
INCLUDEPATH += $$quote($$BASEDIR/src)
|
||||
|
||||
CONFIG += precompile_header
|
||||
|
||||
PRECOMPILED_HEADER = $$quote($$BASEDIR/precompiled.h)
|
||||
|
@ -144,6 +149,9 @@ lupdate_inclusion {
|
|||
$$quote($$BASEDIR/../src/*.cc) \
|
||||
$$quote($$BASEDIR/../src/*.cpp) \
|
||||
$$quote($$BASEDIR/../src/*.cxx) \
|
||||
$$quote($$BASEDIR/..//*.qml) \
|
||||
$$quote($$BASEDIR/..//*.js) \
|
||||
$$quote($$BASEDIR/..//*.qs) \
|
||||
$$quote($$BASEDIR/../assets/*.qml) \
|
||||
$$quote($$BASEDIR/../assets/*.js) \
|
||||
$$quote($$BASEDIR/../assets/*.qs) \
|
||||
|
|
105
src/Pnut.cpp
105
src/Pnut.cpp
|
@ -20,6 +20,8 @@
|
|||
#include "Pnut.h"
|
||||
#include "globals.h"
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include <QRegExp>
|
||||
#include <bb/data/JsonDataAccess>
|
||||
|
||||
const QString Pnut::PNUT_API_ROOT = QString("https://api.pnut.io/v0");
|
||||
|
@ -214,7 +216,8 @@ void Pnut::onAuthorizedRequestReady(QByteArray data, int id)
|
|||
endpoint == "/users/me/bookmarks")
|
||||
{
|
||||
Pnut::RequestType rtype = rtype_map[id];
|
||||
emit streamReceived(variant.toMap()["data"].toList(), rtype);
|
||||
QVariantList streamlist = variant.toMap()["data"].toList();
|
||||
emit streamReceived(parseStream(streamlist), rtype);
|
||||
req_map.remove(id);
|
||||
rtype_map.remove(id);
|
||||
}
|
||||
|
@ -225,7 +228,8 @@ void Pnut::onAuthorizedRequestReady(QByteArray data, int id)
|
|||
}
|
||||
else if (endpoint == ":thread")
|
||||
{
|
||||
emit threadReceived(variant.toMap()["data"].toList());
|
||||
QVariantList streamlist = variant.toMap()["data"].toList();
|
||||
emit threadReceived(parseStream(streamlist));
|
||||
req_map.remove(id);
|
||||
}
|
||||
else if (endpoint == ":userstream")
|
||||
|
@ -299,7 +303,13 @@ void Pnut::onAuthorizedRequestReady(QByteArray data, int id)
|
|||
{
|
||||
qDebug() << "Bookmark successful!";
|
||||
req_map.remove(id);
|
||||
emit postReceived(variant.toMap()["data"].toMap());
|
||||
getPost(variant.toMap()["data"].toMap()["id"].toString());
|
||||
}
|
||||
else if (endpoint.startsWith(":repost"))
|
||||
{
|
||||
qDebug() << "Repost successful!";
|
||||
req_map.remove(id);
|
||||
getPost(variant.toMap()["data"].toMap()["id"].toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -315,6 +325,12 @@ void Pnut::onAuthorizedRequestReady(QByteArray data, int id)
|
|||
qDebug() << "Create post success!";
|
||||
req_map.remove(id);
|
||||
}
|
||||
else if (endpoint.startsWith(":repost"))
|
||||
{
|
||||
qDebug() << "Repost successful!";
|
||||
req_map.remove(id);
|
||||
getPost(variant.toMap()["data"].toMap()["id"].toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Good but not sure what";
|
||||
|
@ -335,7 +351,7 @@ void Pnut::getStream(QString endpoint, Pnut::RequestType rtype)
|
|||
QUrl url(PNUT_API_ROOT + endpoint);
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("count", "50");
|
||||
parameters.insert("include_raw", "1");
|
||||
parameters.insert("include_post_raw", "1");
|
||||
switch (rtype)
|
||||
{
|
||||
case Pnut::STREAM_NEWER:
|
||||
|
@ -350,11 +366,35 @@ void Pnut::getStream(QString endpoint, Pnut::RequestType rtype)
|
|||
getRequest(url, parameters, req_id);
|
||||
}
|
||||
|
||||
void Pnut::sendPost(QString text)
|
||||
void Pnut::sendPost(QString text, int pid=0)
|
||||
{
|
||||
QByteArray post;
|
||||
QVariantMap map;
|
||||
QVariantList raw;
|
||||
|
||||
if (postLength(text) > 256)
|
||||
{
|
||||
QVariantMap longpost;
|
||||
QVariantMap rawobj;
|
||||
longpost["title"] = "";
|
||||
longpost["body"] = text;
|
||||
longpost["tstamp"] = QDateTime::currentMSecsSinceEpoch();
|
||||
rawobj["type"] = "nl.chimpnut.blog.post";
|
||||
rawobj["value"] = longpost;
|
||||
raw.append(rawobj);
|
||||
text.truncate(100);
|
||||
text = text + "... - https://longpo.st/p/{object_id} - #longpost";
|
||||
}
|
||||
map["text"] = text;
|
||||
if (pid > 0)
|
||||
{
|
||||
map["reply_to"] = pid;
|
||||
}
|
||||
if (raw.length() > 0)
|
||||
{
|
||||
map["raw"] = raw;
|
||||
}
|
||||
|
||||
QVariant data(map);
|
||||
bb::data::JsonDataAccess jda;
|
||||
jda.saveToBuffer(data, &post);
|
||||
|
@ -401,7 +441,7 @@ void Pnut::getThread(QString pid)
|
|||
{
|
||||
QUrl url(PNUT_API_ROOT + "/posts/" + pid + "/thread");
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("include_raw", "1");
|
||||
parameters.insert("include_post_raw", "1");
|
||||
req_map[++req_id] = ":thread";
|
||||
getRequest(url, parameters, req_id);
|
||||
}
|
||||
|
@ -410,6 +450,7 @@ void Pnut::setBookmark(QString pid)
|
|||
{
|
||||
QUrl url(PNUT_API_ROOT + "/posts/" + pid + "/bookmark");
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("include_post_raw", "1");
|
||||
req_map[++req_id] = ":bookmark";
|
||||
putRequest(url, parameters, req_id);
|
||||
}
|
||||
|
@ -418,6 +459,7 @@ void Pnut::deleteBookmark(QString pid)
|
|||
{
|
||||
QUrl url(PNUT_API_ROOT + "/posts/" + pid + "/bookmark");
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("include_post_raw", "1");
|
||||
req_map[++req_id] = ":bookmark";
|
||||
deleteRequest(url, parameters, req_id);
|
||||
}
|
||||
|
@ -425,6 +467,7 @@ void Pnut::deleteBookmark(QString pid)
|
|||
void Pnut::repost(QString pid) {
|
||||
QUrl url(PNUT_API_ROOT + "/posts/" + pid + "/repost");
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("include_post_raw", "1");
|
||||
req_map[++req_id] = ":repost";
|
||||
putRequest(url, parameters, req_id);
|
||||
}
|
||||
|
@ -433,6 +476,7 @@ void Pnut::deleteRepost(QString pid)
|
|||
{
|
||||
QUrl url(PNUT_API_ROOT + "/posts/" + pid + "/repost");
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("include_post_raw", "1");
|
||||
req_map[++req_id] = ":repost";
|
||||
deleteRequest(url, parameters, req_id);
|
||||
}
|
||||
|
@ -505,6 +549,7 @@ void Pnut::getPost(QString pid)
|
|||
{
|
||||
QUrl url(PNUT_API_ROOT + "/posts/" + pid);
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("include_post_raw", "1");
|
||||
req_map[++req_id] = ":getpost:" + pid;
|
||||
getRequest(url, parameters, req_id);
|
||||
}
|
||||
|
@ -513,6 +558,8 @@ void Pnut::getUserStream(QString uid)
|
|||
{
|
||||
QUrl url(PNUT_API_ROOT + "/users/" + uid + "/posts");
|
||||
KQOAuthParameters parameters;
|
||||
parameters.insert("count", "150");
|
||||
parameters.insert("include_post_raw", "1");
|
||||
req_map[++req_id] = ":userstream";
|
||||
getRequest(url, parameters, req_id);
|
||||
}
|
||||
|
@ -533,9 +580,55 @@ void Pnut::getFollowing(QString uid)
|
|||
getRequest(url, parameters, req_id);
|
||||
}
|
||||
|
||||
int Pnut::postLength(QString text)
|
||||
{
|
||||
QRegExp mdlink("\\[([^\\]]+)\\][^\\)]+\\)");
|
||||
text.replace(mdlink, "\\1");
|
||||
return text.length();
|
||||
}
|
||||
|
||||
void Pnut::onOpenBrowser(QUrl url)
|
||||
{
|
||||
qDebug() << "_onOpenBrowser_";
|
||||
qDebug() << url;
|
||||
emit openBrowser(url);
|
||||
}
|
||||
|
||||
QVariantList Pnut::parseStream(QVariantList stream)
|
||||
{
|
||||
QVariantList pstream;
|
||||
foreach (QVariant vitem, stream) {
|
||||
QVariantMap item = vitem.toMap();
|
||||
if (item.find("repost_of") != item.end())
|
||||
{
|
||||
QString username = item["user"].toMap()["username"].toString();
|
||||
item = item["repost_of"].toMap();
|
||||
item.insert("reposted_by", username);
|
||||
}
|
||||
if (item.find("raw") != item.end())
|
||||
{
|
||||
QVariantList rawlist = item["raw"].toList();
|
||||
foreach (QVariant ritem, rawlist) {
|
||||
QVariantMap raw = ritem.toMap();
|
||||
if (raw["type"] == "io.pnut.core.oembed")
|
||||
{
|
||||
QVariantMap value = raw["value"].toMap();
|
||||
if (value["type"] == "photo")
|
||||
{
|
||||
item.insert("photo_url", value["url"].toString());
|
||||
if (value.find("thumbnail_url") != value.end())
|
||||
{
|
||||
item.insert("thumbnail_url", value["thumbnail_url"].toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (raw["type"] == "nl.chimpnut.blog.post") {
|
||||
QVariantMap value = raw["value"].toMap();
|
||||
item.insert("longpost_body", value["body"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
pstream.append(item);
|
||||
}
|
||||
return pstream;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
Q_INVOKABLE void authorize();
|
||||
Q_INVOKABLE void getStream(QString endpoint, Pnut::RequestType rtype);
|
||||
Q_INVOKABLE void sendPost(QString text);
|
||||
Q_INVOKABLE void sendPost(QString text, int pid);
|
||||
Q_INVOKABLE void sendReply(QString text, int pid);
|
||||
Q_INVOKABLE void getUser(QString uid);
|
||||
Q_INVOKABLE void followUser(QString uid);
|
||||
|
@ -88,6 +88,7 @@ public:
|
|||
Q_INVOKABLE void getUserStream(QString uid);
|
||||
Q_INVOKABLE void getFollowers(QString uid);
|
||||
Q_INVOKABLE void getFollowing(QString uid);
|
||||
Q_INVOKABLE int postLength(QString text);
|
||||
|
||||
public slots:
|
||||
void onRequestReady(QByteArray data);
|
||||
|
@ -131,6 +132,7 @@ private:
|
|||
void postRequest(QUrl url, KQOAuthParameters parameters, int id, QByteArray data);
|
||||
void putRequest(QUrl url, KQOAuthParameters parameters, int id);
|
||||
void deleteRequest(QUrl url, KQOAuthParameters parameters, int id);
|
||||
QVariantList parseStream(QVariantList stream);
|
||||
};
|
||||
|
||||
#endif /* PNUT_H_ */
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
#include "WebImageView.h"
|
||||
#include <bb/cascades/Image>
|
||||
|
||||
QNetworkAccessManager * WebImageView::mNetManager = new QNetworkAccessManager;
|
||||
QNetworkDiskCache * WebImageView::mNetworkDiskCache = new QNetworkDiskCache();
|
||||
|
||||
WebImageView::WebImageView() {
|
||||
mNetworkDiskCache->setCacheDirectory(QDesktopServices::storageLocation(QDesktopServices::CacheLocation));
|
||||
mNetManager->setCache(mNetworkDiskCache);
|
||||
}
|
||||
|
||||
const QUrl& WebImageView::url() const {
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
void WebImageView::setUrl(const QUrl& url) {
|
||||
|
||||
mUrl = url;
|
||||
mLoading = 0;
|
||||
|
||||
resetImage();
|
||||
QNetworkRequest request;
|
||||
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
||||
request.setUrl(url);
|
||||
|
||||
QNetworkReply * reply = mNetManager->get(QNetworkRequest(request));
|
||||
connect(reply,SIGNAL(finished()), this, SLOT(imageLoaded()));
|
||||
connect(reply,SIGNAL(downloadProgress ( qint64 , qint64 )), this, SLOT(dowloadProgressed(qint64,qint64)));
|
||||
emit urlChanged();
|
||||
}
|
||||
|
||||
double WebImageView::loading() const {
|
||||
return mLoading;
|
||||
}
|
||||
|
||||
void WebImageView::imageLoaded() {
|
||||
|
||||
QNetworkReply * reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
QVariant possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
|
||||
mRedirectUrl = this->redirectUrl(possibleRedirectUrl.toUrl(),mRedirectUrl);
|
||||
if (!mRedirectUrl.isEmpty()) {
|
||||
this->setUrl(mRedirectUrl);
|
||||
} else {
|
||||
setImage(Image(reply->readAll()));
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
|
||||
}
|
||||
|
||||
void WebImageView::dowloadProgressed(qint64 bytes,qint64 total) {
|
||||
|
||||
|
||||
mLoading = double(bytes)/double(total);
|
||||
emit loadingChanged();
|
||||
|
||||
}
|
||||
|
||||
QUrl WebImageView::redirectUrl(const QUrl& possibleRedirectUrl, const QUrl& oldRedirectUrl) const {
|
||||
QUrl redirectUrl;
|
||||
if (!possibleRedirectUrl.isEmpty() && possibleRedirectUrl != oldRedirectUrl) {
|
||||
redirectUrl = possibleRedirectUrl;
|
||||
}
|
||||
return redirectUrl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef WEBIMAGEVIEW_H_
|
||||
#define WEBIMAGEVIEW_H_
|
||||
|
||||
#include <bb/cascades/ImageView>
|
||||
#include <QUrl>
|
||||
using namespace bb::cascades;
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class WebImageView: public bb::cascades::ImageView {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY (QUrl url READ url WRITE setUrl NOTIFY urlChanged)
|
||||
Q_PROPERTY (float loading READ loading NOTIFY loadingChanged)
|
||||
|
||||
public:
|
||||
WebImageView();
|
||||
const QUrl& url() const;
|
||||
double loading() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setUrl(const QUrl& url);
|
||||
|
||||
private Q_SLOTS:
|
||||
void imageLoaded();
|
||||
void dowloadProgressed(qint64,qint64);
|
||||
|
||||
signals:
|
||||
void urlChanged();
|
||||
void loadingChanged();
|
||||
|
||||
|
||||
private:
|
||||
static QNetworkAccessManager * mNetManager;
|
||||
static QNetworkDiskCache * mNetworkDiskCache;
|
||||
QUrl mUrl;
|
||||
QUrl mRedirectUrl;
|
||||
float mLoading;
|
||||
|
||||
QUrl redirectUrl(const QUrl& possibleRedirectUrl, const QUrl& oldRedirectUrl) const;
|
||||
};
|
||||
|
||||
#endif /* WEBIMAGEVIEW_H_ */
|
|
@ -16,8 +16,9 @@
|
|||
|
||||
#include "applicationui.hpp"
|
||||
#include "Pnut.h"
|
||||
#include "WebImageView.h"
|
||||
#include "ActiveFrameQML.h"
|
||||
#include "netimagemanager.h"
|
||||
#include "netimagetracker.h"
|
||||
|
||||
#include <bb/cascades/Application>
|
||||
#include <bb/cascades/QmlDocument>
|
||||
|
@ -25,6 +26,9 @@
|
|||
#include <bb/cascades/LocaleHandler>
|
||||
#include <bb/ApplicationInfo>
|
||||
#include <bb/system/Clipboard>
|
||||
#include <bb/system/InvokeRequest>
|
||||
#include <bb/system/InvokeManager>
|
||||
#include <bb/system/InvokeTargetReply>
|
||||
|
||||
using namespace bb::cascades;
|
||||
|
||||
|
@ -52,7 +56,8 @@ ApplicationUI::ApplicationUI() :
|
|||
|
||||
qmlRegisterType<Pnut>("com.monkeystew.pnut", 1, 0, "Pnut");
|
||||
qmlRegisterType<QTimer> ("com.monkeystew.qtimer", 1, 0, "QTimer");
|
||||
qmlRegisterType<WebImageView>("org.labsquare", 1, 0, "WebImageView");
|
||||
qmlRegisterType<NetImageTracker>("com.netimage", 1, 0, "NetImageTracker");
|
||||
qmlRegisterType<NetImageManager>("com.netimage", 1, 0, "NetImageManager");
|
||||
|
||||
m_appSettings = new QSettings("Morgan McMillian", "Goober");
|
||||
|
||||
|
@ -101,11 +106,13 @@ QString ApplicationUI::appversion()
|
|||
return appinfo.version();
|
||||
}
|
||||
|
||||
void ApplicationUI::copyText(QByteArray text)
|
||||
void ApplicationUI::copyText(QString text)
|
||||
{
|
||||
bb::system::Clipboard clipboard;
|
||||
clipboard.clear();
|
||||
clipboard.insert("text/plain", text);
|
||||
QByteArray textstr;
|
||||
textstr.append(text.toUtf8());
|
||||
clipboard.insert("text/plain", textstr);
|
||||
}
|
||||
|
||||
void ApplicationUI::onInvoke(const bb::system::InvokeRequest& request)
|
||||
|
@ -115,3 +122,23 @@ void ApplicationUI::onInvoke(const bb::system::InvokeRequest& request)
|
|||
emit createPost(request.data());
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationUI::showImage(const QString& filename)
|
||||
{
|
||||
qDebug() << "showImage called!";
|
||||
bb::system::InvokeManager manager;
|
||||
bb::system::InvokeRequest request;
|
||||
|
||||
request.setUri(QUrl::fromLocalFile(filename));
|
||||
request.setTarget("sys.pictures.card.previewer");
|
||||
request.setAction("bb.action.VIEW");
|
||||
bb::system::InvokeTargetReply *targetReply = manager.invoke(request);
|
||||
manager.setParent(this);
|
||||
|
||||
if (targetReply == NULL) {
|
||||
qDebug() << "InvokeTargetReply is NULL: targetReply = " << targetReply;
|
||||
} else {
|
||||
targetReply->setParent(this);
|
||||
}
|
||||
qDebug() << "targetReply = " << targetReply;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ public:
|
|||
Q_INVOKABLE QVariant setting(const QString &key);
|
||||
Q_INVOKABLE void setSetting(const QString &key, const QString &value);
|
||||
Q_INVOKABLE QString appversion();
|
||||
Q_INVOKABLE void copyText(QByteArray text);
|
||||
Q_INVOKABLE void copyText(QString text);
|
||||
Q_INVOKABLE void showImage(const QString &filename);
|
||||
|
||||
Q_SIGNALS:
|
||||
void createPost(QByteArray text);
|
||||
|
|
199
src/netimagemanager.cpp
Normal file
199
src/netimagemanager.cpp
Normal file
|
@ -0,0 +1,199 @@
|
|||
/* Copyright (c) 2012 Research In Motion Limited.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "netimagemanager.h"
|
||||
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
using namespace bb::cascades;
|
||||
|
||||
|
||||
const char* const NetImageManager::mDefaultId = "netimagemanager";
|
||||
|
||||
NetImageManager::NetImageManager(QObject *parent) :
|
||||
QObject(parent) {
|
||||
mCacheId = mDefaultId;
|
||||
mCacheSize = 125;
|
||||
|
||||
QString diskPath = QDir::homePath() + "/" + mCacheId;
|
||||
|
||||
if (!QDir(diskPath).exists()) {
|
||||
QDir().mkdir(diskPath);
|
||||
}
|
||||
|
||||
// Connect to the sslErrors signal to the onSslErrors() function. This will help us see what errors
|
||||
// we get when connecting to the address given by mWeatherAdress.
|
||||
connect(&mAccessManager,
|
||||
SIGNAL(sslErrors ( QNetworkReply * , const QList<QSslError> & )),
|
||||
this,
|
||||
SLOT(onSslErrors ( QNetworkReply * , const QList<QSslError> & )));
|
||||
|
||||
// Connect to the reply finished signal to httpFinsihed() Slot function.
|
||||
connect(&mAccessManager, SIGNAL(finished(QNetworkReply *)), this,
|
||||
SLOT(httpFinished(QNetworkReply *)));
|
||||
}
|
||||
|
||||
NetImageManager::~NetImageManager() {
|
||||
}
|
||||
|
||||
void NetImageManager::lookUpImage(const QString imageName) {
|
||||
QUrl url = QUrl(imageName);
|
||||
// Check if image is stored on disc
|
||||
// The qHash is a bucket type hash so the doubling is to remove possible collisions.
|
||||
QString diskPath = QDir::homePath() + "/" + mCacheId + "/"
|
||||
+ QString::number(qHash(url.host())) + "_"
|
||||
+ QString::number(qHash(url.path())) + ".JPG";
|
||||
|
||||
QFile imageFile(diskPath);
|
||||
|
||||
// If the file exists, send a signal the image is ready
|
||||
if (imageFile.exists()) {
|
||||
emit imageReady(diskPath, url.toString());
|
||||
} else {
|
||||
// otherwise let's download the file, but first we show a loading image
|
||||
emit imageReady(imageName, "loading");
|
||||
|
||||
QNetworkRequest request(url);
|
||||
if (mQueue.isEmpty()) {
|
||||
mAccessManager.get(request);
|
||||
}
|
||||
|
||||
mQueue.append(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NetImageManager::setCacheId(QString cacheId) {
|
||||
if (mCacheId != cacheId) {
|
||||
mCacheId = cacheId;
|
||||
|
||||
QString diskPath = QDir::homePath() + "/" + mCacheId;
|
||||
|
||||
if (!QDir(diskPath).exists()) {
|
||||
QDir().mkdir(diskPath);
|
||||
}
|
||||
|
||||
emit cacheIdChanged(mCacheId);
|
||||
}
|
||||
houseKeep();
|
||||
}
|
||||
|
||||
QString NetImageManager::cacheId() {
|
||||
return mCacheId;
|
||||
}
|
||||
|
||||
void NetImageManager::setCacheSize(int cacheSize) {
|
||||
if (mCacheSize != cacheSize) {
|
||||
mCacheSize = cacheSize;
|
||||
emit cacheSizeChanged(mCacheSize);
|
||||
}
|
||||
houseKeep();
|
||||
}
|
||||
|
||||
int NetImageManager::cacheSize() {
|
||||
return mCacheSize;
|
||||
}
|
||||
|
||||
void NetImageManager::houseKeep() {
|
||||
QString diskPath = QDir::homePath() + "/" + mCacheId + "/";
|
||||
|
||||
QDir directory(diskPath);
|
||||
|
||||
if (directory.count() > (uint) mCacheSize) {
|
||||
//Find the oldest file and delete it.
|
||||
QFileInfoList list = directory.entryInfoList(QDir::Files, QDir::Time);
|
||||
QFile::remove(list.at(list.size() - 1).absoluteFilePath());
|
||||
//maybe there are more then the permitted amount of files here, let's call housekeeping again
|
||||
houseKeep();
|
||||
}
|
||||
}
|
||||
|
||||
void NetImageManager::httpFinished(QNetworkReply * reply) {
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
QImage qImage;
|
||||
qImage.loadFromData(reply->readAll());
|
||||
|
||||
if (qImage.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// When the download is finished we make a hash-tag for the image out of it's url so we can find it again,
|
||||
// then we save it as a .JPG. The qHash is a bucket type hash so the doubling is to remove possible collisions.
|
||||
QString diskPath = QDir::homePath() + "/" + mCacheId + "/"
|
||||
+ QString::number(qHash(reply->url().host())) + "_"
|
||||
+ QString::number(qHash(reply->url().path())) + ".JPG";
|
||||
|
||||
if (qImage.save(diskPath)) {
|
||||
// houseKeep() is called to see that we don't save more then we are allowed in the cache
|
||||
houseKeep();
|
||||
emit imageReady(diskPath, reply->url().toString());
|
||||
}
|
||||
|
||||
//we remove the first item in the download queue
|
||||
if (!mQueue.isEmpty()) {
|
||||
mQueue.removeFirst();
|
||||
|
||||
if (!mQueue.isEmpty()) {
|
||||
QNetworkRequest request = mQueue.first();
|
||||
mAccessManager.get(request);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Handle error
|
||||
qDebug() << "Could Not access image" << reply->url().toString();
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
void NetImageManager::onDialogFinished(bb::system::SystemUiResult::Type type)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void NetImageManager::onSslErrors(QNetworkReply * reply,
|
||||
const QList<QSslError> & errors) {
|
||||
|
||||
foreach (QSslError e, errors)
|
||||
qDebug() << "SSL error: " << e;
|
||||
|
||||
|
||||
|
||||
SystemDialog *dialog = new SystemDialog("OK");
|
||||
|
||||
dialog->setTitle(tr("SSL errors received"));
|
||||
dialog->setBody(tr("We have received information about a security breach in the protocol. Press \"OK\" to terminate the application"));
|
||||
|
||||
|
||||
// Connect your functions to handle the predefined signals for the buttons.
|
||||
// The slot will check the SystemUiResult to see which button was clicked.
|
||||
|
||||
bool success = connect(dialog,
|
||||
SIGNAL(finished(bb::system::SystemUiResult::Type)),
|
||||
this,
|
||||
SLOT(onDialogFinished(bb::system::SystemUiResult::Type)));
|
||||
|
||||
if (success) {
|
||||
// Signal was successfully connected.
|
||||
// Now show the dialog box in your UI
|
||||
|
||||
dialog->show();
|
||||
} else {
|
||||
// Failed to connect to signal.
|
||||
dialog->deleteLater();
|
||||
}
|
||||
|
||||
}
|
146
src/netimagemanager.h
Normal file
146
src/netimagemanager.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
/* Copyright (c) 2012 Research In Motion Limited.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef _NETIMAGECACHE_H_
|
||||
#define _NETIMAGECACHE_H_
|
||||
|
||||
#include <bb/cascades/Image>
|
||||
#include <bb/system/SystemDialog>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
using namespace bb::cascades;
|
||||
using namespace bb::system;
|
||||
|
||||
/**
|
||||
* NetImageManager is a cache service for our Internet downloaded images.
|
||||
* You can set the size of the cache and an id for the cache.
|
||||
* If you want to reuse the cache between different pages it's possible.
|
||||
*/
|
||||
class NetImageManager: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* This property sets the name of the image cache, if none is set we will use it to the
|
||||
* default "netimagemanager".
|
||||
*/
|
||||
Q_PROPERTY(QString cacheId READ cacheId WRITE setCacheId NOTIFY cacheIdChanged)
|
||||
|
||||
/**
|
||||
* Sets the size of the cache in number of files in the directory, if not set, it defaults
|
||||
* to 125 files.
|
||||
*/
|
||||
Q_PROPERTY(int cacheSize READ cacheSize WRITE setCacheSize NOTIFY cacheSizeChanged)
|
||||
|
||||
public:
|
||||
/**
|
||||
* This is our constructor which initializes the member variables.
|
||||
* @param parent The parent QObject, if not specified, 0 is used.
|
||||
*/
|
||||
NetImageManager(QObject *parent = 0);
|
||||
~NetImageManager();
|
||||
|
||||
/**
|
||||
* This function sets the cacheId property.
|
||||
*
|
||||
* @param cacheId The cacheId used for storing downloaded in a folder.
|
||||
*/
|
||||
void setCacheId(QString cacheId);
|
||||
|
||||
/**
|
||||
* This function return the chacheId, that is the location of the folder where images
|
||||
* are stored for the cache object.
|
||||
*
|
||||
* @return The cacheId
|
||||
*/
|
||||
QString cacheId();
|
||||
|
||||
/**
|
||||
* This function sets the cacheSize property.
|
||||
*
|
||||
* @param cacheId The cacheSize used for cleaning the cache folder.
|
||||
*/
|
||||
void setCacheSize(int cacheSize);
|
||||
|
||||
/**
|
||||
* This function return the chacheSize.
|
||||
*
|
||||
* @return The cacheId
|
||||
*/
|
||||
int cacheSize();
|
||||
|
||||
/**
|
||||
* Check if the image exists in cache
|
||||
*
|
||||
* @return the full path to the image if it exists otherwise 0
|
||||
*/
|
||||
QString getNetImage(QString imageName);
|
||||
|
||||
void lookUpImage(const QString imageName);
|
||||
|
||||
/**
|
||||
* Check if the cache is full and if so deletes the oldest
|
||||
*/
|
||||
void houseKeep();
|
||||
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Slot called for by the dialog that you get with SSL-errors
|
||||
*/
|
||||
void onDialogFinished(bb::system::SystemUiResult::Type type);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted when a new cacheId has been set
|
||||
*/
|
||||
void cacheIdChanged(QString cacheId);
|
||||
void cacheSizeChanged(int cacheSize);
|
||||
|
||||
void imageReady(const QString filePath, const QString imageName);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* This Slot function is called when the network request is complete.
|
||||
*/
|
||||
void httpFinished( QNetworkReply * reply );
|
||||
|
||||
/**
|
||||
* This Slot function is connected to the mAccessManager sslErrors signal. This function
|
||||
* allows us to see what errors we get when connecting to the address given by mWeatherAdress.
|
||||
*
|
||||
* @param reply The network reply
|
||||
* @param errors SSL Error List
|
||||
*/
|
||||
void onSslErrors(QNetworkReply * reply, const QList<QSslError> & errors);
|
||||
|
||||
private:
|
||||
|
||||
// Property variables
|
||||
QString mCacheId;
|
||||
int mCacheSize;
|
||||
|
||||
// String constant for the default id of the image cache
|
||||
static const char* const mDefaultId;
|
||||
|
||||
// The network parameters; used for accessing a file from the Internet
|
||||
QNetworkAccessManager mAccessManager;
|
||||
|
||||
QList<QNetworkRequest> mQueue;
|
||||
};
|
||||
|
||||
#endif // _NETIMAGECACHE_H_
|
108
src/netimagetracker.cpp
Normal file
108
src/netimagetracker.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* Copyright (c) 2012 Research In Motion Limited.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "netimagetracker.h"
|
||||
#include <bb/cascades/ImageTracker>
|
||||
|
||||
using namespace bb;
|
||||
using namespace bb::cascades;
|
||||
|
||||
NetImageTracker::NetImageTracker(QObject *parent) :
|
||||
ImageTracker(parent), mManager(0)
|
||||
{
|
||||
mIsCreated = false;
|
||||
|
||||
connect(this, SIGNAL(creationCompleted()), this, SLOT(onCreationCompleted()));
|
||||
}
|
||||
|
||||
void NetImageTracker::onCreationCompleted()
|
||||
{
|
||||
mIsCreated = true;
|
||||
|
||||
if (!mSource.isEmpty() && mManager) {
|
||||
// Once creation of the tracker has completed, the lookup of the image is ready to
|
||||
// be executed. If the tracker is used within a list item this lookup is not needed
|
||||
// since the update of list item data will enforce a refresh of the imageSource that
|
||||
// will perform the lookup. But for the tracker to work in ImageViews that are not
|
||||
// part of a list item we need this here.
|
||||
mManager->lookUpImage(mSource);
|
||||
}
|
||||
}
|
||||
|
||||
void NetImageTracker::onImageReady(const QString filePath, const QString imageName)
|
||||
{
|
||||
// The NetImageManager will emit a signal to all NetImageTrackers, make sure the
|
||||
// image that is ready belongs to this tracker.
|
||||
if (imageName.compare(mSource) == 0) {
|
||||
if (imageName.compare("loading") == 0) {
|
||||
// If we don't have an image to display, let's display a loading image
|
||||
QUrl url = QUrl("asset:///icons/ic_doctype_picture.png");
|
||||
setImageSource(url);
|
||||
} else {
|
||||
// Set the path to the image that is now downloaded and cached in the data folder on the device.
|
||||
QUrl url = QUrl(filePath);
|
||||
setImageSource(url);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetImageTracker::setSource(const QString source)
|
||||
{
|
||||
if (!source.isEmpty() && mSource.compare(source) != 0) {
|
||||
mSource = source;
|
||||
|
||||
if (mManager) {
|
||||
// If a manger has been set make a request to look up the image. Otherwise
|
||||
// the request is delayed to onCreationCompleted or at the next time a call
|
||||
// to set the source is made.
|
||||
mManager->lookUpImage(mSource);
|
||||
} else {
|
||||
qWarning()
|
||||
<< "This NetImageTracker does not have any NetImageManager, set up one as an attached object and add it to the property.";
|
||||
}
|
||||
|
||||
emit sourceChanged(mSource);
|
||||
}
|
||||
}
|
||||
|
||||
QString NetImageTracker::source()
|
||||
{
|
||||
return mSource;
|
||||
}
|
||||
|
||||
void NetImageTracker::setManager(NetImageManager *manager)
|
||||
{
|
||||
if (mManager != manager) {
|
||||
|
||||
// Change the manager that is used for the tracker.
|
||||
if (mManager) {
|
||||
disconnect(mManager, SIGNAL(imageReady(const QString , const QString )), this,
|
||||
SLOT(onImageReady( const QString , const QString )));
|
||||
delete (mManager);
|
||||
}
|
||||
|
||||
mManager = manager;
|
||||
emit managerChanged(mManager);
|
||||
|
||||
connect(mManager, SIGNAL(imageReady(const QString , const QString )), this,
|
||||
SLOT(onImageReady( const QString , const QString )));
|
||||
}
|
||||
}
|
||||
|
||||
NetImageManager *NetImageTracker::manager()
|
||||
{
|
||||
return mManager;
|
||||
}
|
||||
|
115
src/netimagetracker.h
Normal file
115
src/netimagetracker.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/* Copyright (c) 2012 Research In Motion Limited.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _NETIMAGETRACKER_H_
|
||||
#define _NETIMAGETRACKER_H_
|
||||
|
||||
#include "netimagemanager.h"
|
||||
#include <bb/cascades/ImageTracker>
|
||||
|
||||
using namespace bb::cascades;
|
||||
|
||||
/**
|
||||
* The NetImageTracker is used so that Cascades can be informed when an image is downloaded
|
||||
* via a NetImageManager.
|
||||
*/
|
||||
class NetImageTracker: public bb::cascades::ImageTracker
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* The NetImageManager property points to a manager that is used for downloading and caching
|
||||
* images.
|
||||
*/
|
||||
Q_PROPERTY(NetImageManager *manager READ manager WRITE setManager NOTIFY managerChanged)
|
||||
|
||||
/**
|
||||
* Sets the NetImageTracker source, the remote networked url that points to the image.
|
||||
* You need to set one as an attached object in your QML files.
|
||||
*/
|
||||
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor; Sets up the net image view
|
||||
* @param parent The parent Container.
|
||||
*/
|
||||
NetImageTracker(QObject *parent = 0);
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* Setter function for setting the trackers net image manager
|
||||
*
|
||||
* @param manager in manager that we're going to use.
|
||||
*/
|
||||
void setManager(NetImageManager *manager);
|
||||
|
||||
/**
|
||||
* Getter for Trackers Manager object
|
||||
* @return
|
||||
*/
|
||||
NetImageManager *manager();
|
||||
|
||||
/**
|
||||
* Setter for the source object.
|
||||
*
|
||||
* @param source in string with path to the source.
|
||||
*/
|
||||
void setSource(const QString source);
|
||||
|
||||
/**
|
||||
* Getter for source
|
||||
* @return a string of the source
|
||||
*/
|
||||
QString source();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Signal that emits when the source have changed, wont happen automatically
|
||||
*
|
||||
* @param source the new source
|
||||
*/
|
||||
void sourceChanged(QString source);
|
||||
|
||||
/**
|
||||
* signal that is emitted if the manager is changed, will not happen automatically.
|
||||
*
|
||||
* @param imageCache the new NetImageManager we want to have .
|
||||
*/
|
||||
void managerChanged(NetImageManager *imageCache);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Emitted when we are done with the setup of this class
|
||||
*/
|
||||
void onCreationCompleted();
|
||||
|
||||
/**
|
||||
* Emitted when we have a image that is ready for consumption
|
||||
*
|
||||
* @param filePath the path to the image that we can do what we want with
|
||||
* @param imageName the actual name of the file, useful!
|
||||
*/
|
||||
void onImageReady(const QString filePath, const QString imageName);
|
||||
|
||||
private:
|
||||
QString mSource;
|
||||
|
||||
NetImageManager *mManager;
|
||||
bool mIsCreated;
|
||||
};
|
||||
|
||||
#endif // ifndef _NETIMAGETRACKER_H_
|
|
@ -9,20 +9,33 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NetImageManager</name>
|
||||
<message>
|
||||
<location filename="../src/netimagemanager.cpp" line="177"/>
|
||||
<source>SSL errors received</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/netimagemanager.cpp" line="178"/>
|
||||
<source>We have received information about a security breach in the protocol. Press "OK" to terminate the application</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NewPostSheet</name>
|
||||
<message>
|
||||
<location filename="../assets/NewPostSheet.qml" line="35"/>
|
||||
<location filename="../assets/NewPostSheet.qml" line="37"/>
|
||||
<source>Send</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/NewPostSheet.qml" line="44"/>
|
||||
<location filename="../assets/NewPostSheet.qml" line="46"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/NewPostSheet.qml" line="50"/>
|
||||
<location filename="../assets/NewPostSheet.qml" line="52"/>
|
||||
<source>New Post</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -30,52 +43,52 @@
|
|||
<context>
|
||||
<name>PostItem</name>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="189"/>
|
||||
<location filename="../assets/PostItem.qml" line="280"/>
|
||||
<source>Reply</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="198"/>
|
||||
<location filename="../assets/PostItem.qml" line="289"/>
|
||||
<source>Reply All</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="208"/>
|
||||
<source>Add Bookmark</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="208"/>
|
||||
<location filename="../assets/PostItem.qml" line="299"/>
|
||||
<source>Delete Bookmark</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="219"/>
|
||||
<source>Repost</source>
|
||||
<location filename="../assets/PostItem.qml" line="299"/>
|
||||
<source>Add Bookmark</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="219"/>
|
||||
<location filename="../assets/PostItem.qml" line="310"/>
|
||||
<source>Delete Repost</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="230"/>
|
||||
<location filename="../assets/PostItem.qml" line="310"/>
|
||||
<source>Repost</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="321"/>
|
||||
<source>Quote</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="239"/>
|
||||
<location filename="../assets/PostItem.qml" line="330"/>
|
||||
<source>View Profile</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="246"/>
|
||||
<location filename="../assets/PostItem.qml" line="337"/>
|
||||
<source>Copy text</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/PostItem.qml" line="276"/>
|
||||
<location filename="../assets/PostItem.qml" line="367"/>
|
||||
<source>Delete</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -83,55 +96,55 @@
|
|||
<context>
|
||||
<name>ProfilePage</name>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="128"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="201"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="145"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="218"/>
|
||||
<source>Following</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="141"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="216"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="158"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="233"/>
|
||||
<source>Followers</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="154"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="188"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="171"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="205"/>
|
||||
<source>Posts</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="167"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="184"/>
|
||||
<source>Bookmarks</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="233"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="250"/>
|
||||
<source>Unfollow</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="233"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="250"/>
|
||||
<source>Follow</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="246"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="263"/>
|
||||
<source>Unmute</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="246"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="263"/>
|
||||
<source>Mute</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="259"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="276"/>
|
||||
<source>Unblock</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/ProfilePage.qml" line="259"/>
|
||||
<location filename="../assets/ProfilePage.qml" line="276"/>
|
||||
<source>Block</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -172,17 +185,47 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="117"/>
|
||||
<location filename="../assets/SettingsPage.qml" line="121"/>
|
||||
<source>Hide photos</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="126"/>
|
||||
<source>Hide embeded photos in timeline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="160"/>
|
||||
<source>Hide avatars</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="165"/>
|
||||
<source>Hide avatar images in timeline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="199"/>
|
||||
<source>Hide long posts</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="204"/>
|
||||
<source>Hide long posts in timeline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="234"/>
|
||||
<source>Theme</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="119"/>
|
||||
<location filename="../assets/SettingsPage.qml" line="236"/>
|
||||
<source>Bright</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/SettingsPage.qml" line="124"/>
|
||||
<location filename="../assets/SettingsPage.qml" line="241"/>
|
||||
<source>Dark</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -190,22 +233,22 @@
|
|||
<context>
|
||||
<name>StreamTab</name>
|
||||
<message>
|
||||
<location filename="../assets/StreamTab.qml" line="143"/>
|
||||
<location filename="../assets/StreamTab.qml" line="185"/>
|
||||
<source>New Post</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/StreamTab.qml" line="157"/>
|
||||
<location filename="../assets/StreamTab.qml" line="199"/>
|
||||
<source>To Top</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/StreamTab.qml" line="185"/>
|
||||
<location filename="../assets/StreamTab.qml" line="227"/>
|
||||
<source>To Bottom</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/StreamTab.qml" line="172"/>
|
||||
<location filename="../assets/StreamTab.qml" line="214"/>
|
||||
<source>Reload</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -213,12 +256,12 @@
|
|||
<context>
|
||||
<name>UserItem</name>
|
||||
<message>
|
||||
<location filename="../assets/UserItem.qml" line="54"/>
|
||||
<location filename="../assets/UserItem.qml" line="68"/>
|
||||
<source>Unfollow</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/UserItem.qml" line="54"/>
|
||||
<location filename="../assets/UserItem.qml" line="68"/>
|
||||
<source>Follow</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -236,26 +279,26 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/main.qml" line="68"/>
|
||||
<location filename="../assets/main.qml" line="72"/>
|
||||
<location filename="../assets/main.qml" line="74"/>
|
||||
<location filename="../assets/main.qml" line="78"/>
|
||||
<source>Home</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/main.qml" line="90"/>
|
||||
<location filename="../assets/main.qml" line="94"/>
|
||||
<location filename="../assets/main.qml" line="96"/>
|
||||
<location filename="../assets/main.qml" line="100"/>
|
||||
<source>Mentions</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/main.qml" line="112"/>
|
||||
<location filename="../assets/main.qml" line="116"/>
|
||||
<location filename="../assets/main.qml" line="118"/>
|
||||
<location filename="../assets/main.qml" line="122"/>
|
||||
<source>Bookmarks</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../assets/main.qml" line="134"/>
|
||||
<location filename="../assets/main.qml" line="138"/>
|
||||
<location filename="../assets/main.qml" line="140"/>
|
||||
<location filename="../assets/main.qml" line="144"/>
|
||||
<source>Global</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
Reference in a new issue