Skip to content

Commit

Permalink
Merge pull request #97 from ioriayane/Release/v0.16.0
Browse files Browse the repository at this point in the history
Release v0.16.0
  • Loading branch information
ioriayane authored Nov 24, 2023
2 parents 0d21d7f + 2380318 commit d6db74d
Show file tree
Hide file tree
Showing 64 changed files with 1,231 additions and 556 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"console": "integratedTerminal",
"justMyCode": true,
"args": [
"../atproto/lexicons",
"./1stparty/atproto/lexicons",
"./lib/atprotocol"
]
}
Expand Down
2 changes: 1 addition & 1 deletion app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ int main(int argc, char *argv[])
app.setOrganizationName(QStringLiteral("relog"));
app.setOrganizationDomain(QStringLiteral("hagoromo.relog.tech"));
app.setApplicationName(QStringLiteral("Hagoromo"));
app.setApplicationVersion(QStringLiteral("0.15.0"));
app.setApplicationVersion(QStringLiteral("0.16.0"));
#ifndef HAGOROMO_RELEASE_BUILD
app.setApplicationVersion(app.applicationVersion() + "d");
#endif
Expand Down
4 changes: 3 additions & 1 deletion app/qml/controls/ImageWithIndicator.qml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import QtQuick 2.15
import QtQuick.Controls 2.15

Image {
AnimatedImage {
id: imageWithIndicator
onStatusChanged: playing = (status == AnimatedImage.Ready)

BusyIndicator {
anchors.centerIn: parent
width: parent.width > 100 ? 100 : parent.width
Expand Down
2 changes: 1 addition & 1 deletion app/qml/dialogs/PostDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ Dialog {
title: qsTr("Select contents")
visible: false
fileMode : P.FileDialog.OpenFiles
nameFilters: ["Image files (*.jpg *.jpeg *.png)"
nameFilters: ["Image files (*.jpg *.jpeg *.png *.gif)"
, "All files (*)"]
onAccepted: {
//選択されたファイルをすべて追加
Expand Down
4 changes: 1 addition & 3 deletions app/qml/view/ColumnView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,8 @@ ColumnLayout {
TimelineView {
model: SearchPostListModel {
autoLoading: settings.autoLoading
//loadingInterval: settings.loadingInterval
loadingInterval: settings.loadingInterval
text: settings.columnValue
searchService: "https://search.bsky.social"

onErrorOccured: (code, message) => columnView.errorOccured(columnView.account.uuid, code, message)
}
Expand Down Expand Up @@ -247,7 +246,6 @@ ColumnLayout {
model: SearchProfileListModel {
autoLoading: settings.autoLoading
text: settings.columnValue
searchService: "https://search.bsky.social"

onErrorOccured: (code, message) => columnView.errorOccured(columnView.account.uuid, code, message)
}
Expand Down
141 changes: 141 additions & 0 deletions app/qtquick/atpabstractlistmodel.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#include "atpabstractlistmodel.h"
#include "atprotocol/com/atproto/sync/comatprotosyncgetblob.h"
#include "atprotocol/lexicons_func_unknown.h"
#include "translator.h"
#include "common.h"

#include <QDesktopServices>
#include <QUrlQuery>

using namespace AtProtocolType;
using AtProtocolInterface::ComAtprotoSyncGetBlob;

AtpAbstractListModel::AtpAbstractListModel(QObject *parent)
: QAbstractListModel { parent },
Expand Down Expand Up @@ -429,6 +432,144 @@ QString AtpAbstractListModel::getVia(const QVariant &record) const
return LexiconsTypeUnknown::fromQVariant<AppBskyFeedPost::Main>(record).via;
}

void AtpAbstractListModel::appendExtendMediaFileToClue(const QString &did, const QString &cid,
const QString &parent_cid)
{
if (did.isEmpty() || cid.isEmpty() || parent_cid.isEmpty()) {
return;
} else {
m_cueExtendMedia.append(BlobCueItem(did, cid, parent_cid));
}
}

void AtpAbstractListModel::getExtendMediaFiles()
{
BlobCueItem blob_item;
if (m_cueExtendMedia.isEmpty()) {
return;
} else {
blob_item = m_cueExtendMedia.front();
m_cueExtendMedia.pop_front();
}

ComAtprotoSyncGetBlob *blob = new ComAtprotoSyncGetBlob(this);
connect(blob, &ComAtprotoSyncGetBlob::finished, [=](bool success) {
if (success) {
QString path = saveMediaFile(blob->blobData(), blob_item.cid, blob->extension());
if (!path.isEmpty()) {
updateExtendMediaFile(blob_item.parent_cid);
}
}
QTimer::singleShot(10, this, &AtpAbstractListModel::getExtendMediaFiles);
blob->deleteLater();
});
blob->setAccount(account());
blob->getBlob(blob_item.did, blob_item.cid);
}

QString AtpAbstractListModel::getMediaFilePath(const QString &cid, const QString &ext) const
{
QString folder = Common::appTempFolder("ext_images");
return QString("%1/%2.%3").arg(folder, cid, ext);
}

QString AtpAbstractListModel::saveMediaFile(const QByteArray &data, const QString &cid,
const QString &ext)
{
QString path = getMediaFilePath(cid, ext);
QFile out(path);
if (out.open(QFile::WriteOnly)) {
qDebug().noquote().nospace() << "Save extend media file : " << path;
out.write(data);
out.close();
return path;
}
return QString();
}

void AtpAbstractListModel::updateExtendMediaFile(const QString &parent_cid)
{
Q_UNUSED(parent_cid)
}

// 画像URLを取得する
// recordのembed/blobにgifがある場合はローカルに保存されているファイルパスを返す
// 無ければ通常のサムネ画像のURLを返す
QStringList AtpAbstractListModel::copyImagesFromPostView(
const AtProtocolType::AppBskyFeedDefs::PostView &post,
const AtProtocolType::LexiconsTypeUnknown::CopyImageType type) const
{
QStringList ret = LexiconsTypeUnknown::copyImagesFromPostView(post, type);

const AppBskyFeedPost::Main record =
LexiconsTypeUnknown::fromQVariant<AppBskyFeedPost::Main>(post.record);
for (int i = 0; i < record.embed_AppBskyEmbedImages_Main.images.length(); i++) {
const auto &image = record.embed_AppBskyEmbedImages_Main.images.at(i);
if (image.image.mimeType != "image/gif")
continue;
QString path = getMediaFilePath(image.image.cid,
Common::mimeTypeToExtension(image.image.mimeType));
if (QFile::exists(path)) {
path = QUrl::fromLocalFile(path).toString();
if (i < ret.length()) {
ret[i] = path;
} else {
ret.append(path);
}
}
}
for (int i = 0; i < record.embed_AppBskyEmbedRecordWithMedia_Main.media_AppBskyEmbedImages_Main
.images.length();
i++) {
const auto &image = record.embed_AppBskyEmbedRecordWithMedia_Main
.media_AppBskyEmbedImages_Main.images.at(i);
if (image.image.mimeType != "image/gif")
continue;
QString path = getMediaFilePath(image.image.cid,
Common::mimeTypeToExtension(image.image.mimeType));
if (QFile::exists(path)) {
path = QUrl::fromLocalFile(path).toString();
if (i < ret.length()) {
ret[i] = path;
} else {
ret.append(path);
}
}
}
return ret;
}

// recordのembed/blobにgifがあればgetBlobするためのキューに入れる
void AtpAbstractListModel::copyImagesFromPostViewToCue(
const AtProtocolType::AppBskyFeedDefs::PostView &post)
{
const AppBskyFeedPost::Main record =
LexiconsTypeUnknown::fromQVariant<AppBskyFeedPost::Main>(post.record);
for (int i = 0; i < record.embed_AppBskyEmbedImages_Main.images.length(); i++) {
const auto &image = record.embed_AppBskyEmbedImages_Main.images.at(i);
if (image.image.mimeType != "image/gif")
continue;
QString path = getMediaFilePath(image.image.cid,
Common::mimeTypeToExtension(image.image.mimeType));
if (!QFile::exists(path)) {
appendExtendMediaFileToClue(post.author.did, image.image.cid, post.cid);
}
}
for (int i = 0; i < record.embed_AppBskyEmbedRecordWithMedia_Main.media_AppBskyEmbedImages_Main
.images.length();
i++) {
const auto &image = record.embed_AppBskyEmbedRecordWithMedia_Main
.media_AppBskyEmbedImages_Main.images.at(i);
if (image.image.mimeType != "image/gif")
continue;
QString path = getMediaFilePath(image.image.cid,
Common::mimeTypeToExtension(image.image.mimeType));
if (!QFile::exists(path)) {
appendExtendMediaFileToClue(post.author.did, image.image.cid, post.cid);
}
}
}

QString AtpAbstractListModel::cursor() const
{
return m_cursor;
Expand Down
29 changes: 29 additions & 0 deletions app/qtquick/atpabstractlistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "atprotocol/accessatprotocol.h"
#include "atprotocol/lexicons.h"
#include "atprotocol/lexicons_func_unknown.h"
#include "tools/configurablelabels.h"

#include <QAbstractListModel>
Expand All @@ -19,6 +20,20 @@ struct PostCueItem
AtProtocolType::AppBskyFeedDefs::FeedViewPostReasonType::none;
};

struct BlobCueItem
{
BlobCueItem() {};
BlobCueItem(const QString &did, const QString &cid, const QString &parent_cid)
{
this->did = did;
this->cid = cid;
this->parent_cid = parent_cid;
}
QString did;
QString cid;
QString parent_cid;
};

class AtpAbstractListModel : public QAbstractListModel
{
Q_OBJECT
Expand Down Expand Up @@ -100,6 +115,18 @@ public slots:
QStringList getLaunguages(const QVariant &record) const;
QString getVia(const QVariant &record) const;

void appendExtendMediaFileToClue(const QString &did, const QString &cid,
const QString &parent_cid);
void getExtendMediaFiles();
QString getMediaFilePath(const QString &cid, const QString &ext) const;
QString saveMediaFile(const QByteArray &data, const QString &cid, const QString &ext);
virtual void updateExtendMediaFile(const QString &parent_cid);

QStringList
copyImagesFromPostView(const AtProtocolType::AppBskyFeedDefs::PostView &post,
const AtProtocolType::LexiconsTypeUnknown::CopyImageType type) const;
void copyImagesFromPostViewToCue(const AtProtocolType::AppBskyFeedDefs::PostView &post);

// これで取得したポストの順番を管理して実態はm_viewPostHashで管理
// checkVisibility(cid)の結果次第で間引かれる
QList<QString> m_cidList;
Expand All @@ -111,6 +138,8 @@ public slots:

QHash<QString, QString> m_translations; // QHash<cid, translation>

QList<BlobCueItem> m_cueExtendMedia;

ConfigurableLabels m_contentFilterLabels;

private:
Expand Down
22 changes: 22 additions & 0 deletions app/qtquick/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,28 @@ inline QString appDataFolder()
);
}

inline QString appTempFolder(const QString &sub = QString())
{
QString folder =
QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::TempLocation),
QCoreApplication::applicationName());
if (!sub.isEmpty()) {
folder.append("/" + sub);
}
QDir dir(folder);
dir.mkpath(folder);
return folder;
}

inline QString mimeTypeToExtension(const QString &mime_type)
{
QStringList items = mime_type.split("/");
if (items.length() == 2) {
return items.last();
}
return mime_type;
}

inline void saveJsonDocument(const QJsonDocument &doc, const QString &file_name)
{
QString folder = Common::appDataFolder();
Expand Down
62 changes: 22 additions & 40 deletions app/qtquick/followerslistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,24 @@ bool FollowersListModel::getLatest()
setRunning(true);

return updateContentFilterLabels([=]() {
AppBskyGraphGetFollowers *followers = new AppBskyGraphGetFollowers(this);
connect(followers, &AppBskyGraphGetFollowers::finished, [=](bool success) {
AppBskyGraphGetFollowers *profiles = new AppBskyGraphGetFollowers(this);
connect(profiles, &AppBskyGraphGetFollowers::finished, [=](bool success) {
if (success) {
if (m_didList.isEmpty()) {
m_cursor = followers->cursor();
}
for (const auto &profile : *followers->profileList()) {
m_profileHash[profile.did] = profile;
m_formattedDescriptionHash[profile.did] =
m_systemTool.markupText(profile.description);
if (m_didList.contains(profile.did)) {
int row = m_didList.indexOf(profile.did);
emit dataChanged(index(row), index(row));
} else {
beginInsertRows(QModelIndex(), m_didList.count(), m_didList.count());
m_didList.append(profile.did);
endInsertRows();
}
m_cursor = profiles->cursor();
}
copyProfiles(profiles);
} else {
emit errorOccured(followers->errorCode(), followers->errorMessage());
emit errorOccured(profiles->errorCode(), profiles->errorMessage());
}
setRunning(false);
followers->deleteLater();
profiles->deleteLater();
});
followers->setAccount(account());
followers->getFollowers(targetDid(), 50, QString());
profiles->setAccount(account());
if (!profiles->getFollowers(targetDid(), 50, QString())) {
emit errorOccured(profiles->errorCode(), profiles->errorMessage());
setRunning(false);
}
});
}

Expand All @@ -50,30 +41,21 @@ bool FollowersListModel::getNext()
setRunning(true);

return updateContentFilterLabels([=]() {
AppBskyGraphGetFollowers *followers = new AppBskyGraphGetFollowers(this);
connect(followers, &AppBskyGraphGetFollowers::finished, [=](bool success) {
AppBskyGraphGetFollowers *profiles = new AppBskyGraphGetFollowers(this);
connect(profiles, &AppBskyGraphGetFollowers::finished, [=](bool success) {
if (success) {
m_cursor = followers->cursor();
for (const auto &profile : *followers->profileList()) {
m_profileHash[profile.did] = profile;
m_formattedDescriptionHash[profile.did] =
m_systemTool.markupText(profile.description);
if (m_didList.contains(profile.did)) {
int row = m_didList.indexOf(profile.did);
emit dataChanged(index(row), index(row));
} else {
beginInsertRows(QModelIndex(), m_didList.count(), m_didList.count());
m_didList.append(profile.did);
endInsertRows();
}
}
m_cursor = profiles->cursor();
copyProfiles(profiles);
} else {
emit errorOccured(followers->errorCode(), followers->errorMessage());
emit errorOccured(profiles->errorCode(), profiles->errorMessage());
}
setRunning(false);
followers->deleteLater();
profiles->deleteLater();
});
followers->setAccount(account());
followers->getFollowers(targetDid(), 50, m_cursor);
profiles->setAccount(account());
if (!profiles->getFollowers(targetDid(), 50, m_cursor)) {
emit errorOccured(profiles->errorCode(), profiles->errorMessage());
setRunning(false);
}
});
}
Loading

0 comments on commit d6db74d

Please sign in to comment.