fix gmail attachment names encoding + other gmail stuff

This commit is contained in:
Martin Rotter 2023-04-20 08:46:50 +02:00
parent abebbf7e56
commit fb2c439b40
10 changed files with 49 additions and 23 deletions

View File

@ -6,6 +6,7 @@ Added:
* macOS build is now built with macOS 11.
* Linux build is now built with Ubuntu 20.04 which is now oldest supported Linux LTS distribution.
* Reworked logic of determining which article states (read/unread/starred/unstarred) have changed when synchronizing states to remote feed servers. This concerns all synchronized plugins like Gmail, Greader, Feedly, etc. and show in theory lead to much better performance when you mark many articles as read or unread.
* Couple of extra QoL enhancements for Gmail like proper encoding of attachment filenames, turned off displaying of "enclosures" as these are displayed in other way, etc.
Fixed:
* Deadlock when fetching feeds in some corner situations is now resolved. (#910)

View File

@ -17,7 +17,6 @@
Enclosure::Enclosure(QString url, QString mime) : m_url(std::move(url)), m_mimeType(std::move(mime)) {}
QList<Enclosure> Enclosures::decodeEnclosuresFromString(const QString& enclosures_data) {
QList<Enclosure> enclosures;
auto enc = enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR,
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
Qt::SplitBehaviorFlags::SkipEmptyParts);
@ -25,17 +24,20 @@ QList<Enclosure> Enclosures::decodeEnclosuresFromString(const QString& enclosure
QString::SplitBehavior::SkipEmptyParts);
#endif
QList<Enclosure> enclosures;
enclosures.reserve(enc.size());
for (const QString& single_enclosure : qAsConst(enc)) {
Enclosure enclosure;
if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) {
QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR);
enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit());
enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit());
enclosure.m_mimeType = QString::fromUtf8(QByteArray::fromBase64(mime_url.at(0).toLocal8Bit()));
enclosure.m_url = QString::fromUtf8(QByteArray::fromBase64(mime_url.at(1).toLocal8Bit()));
}
else {
enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit());
enclosure.m_url = QString::fromUtf8(QByteArray::fromBase64(single_enclosure.toLocal8Bit()));
}
enclosures.append(enclosure);
@ -49,11 +51,11 @@ QString Enclosures::encodeEnclosuresToString(const QList<Enclosure>& enclosures)
for (const Enclosure& enclosure : enclosures) {
if (enclosure.m_mimeType.isEmpty()) {
enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64());
enclosures_str.append(enclosure.m_url.toUtf8().toBase64());
}
else {
enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) + ECNLOSURES_INNER_SEPARATOR +
enclosure.m_url.toLocal8Bit().toBase64());
enclosures_str.append(QString(enclosure.m_mimeType.toUtf8().toBase64()) + ECNLOSURES_INNER_SEPARATOR +
enclosure.m_url.toUtf8().toBase64());
}
}

View File

@ -14,7 +14,7 @@
<item>
<widget class="QTabWidget" name="m_tabFeedsMessages">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="m_tabFeeds">
<attribute name="title">
@ -300,7 +300,7 @@
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="m_cbShowEnclosuresDirectly">
<property name="text">
<string>Display attached pictures directly in article</string>
<string>Display attachments directly in article</string>
</property>
</widget>
</item>

View File

@ -88,6 +88,8 @@ QVariant TextBrowserViewer::loadOneResource(int type, const QUrl& name) {
PreparedHtml TextBrowserViewer::prepareHtmlForMessage(const QList<Message>& messages, RootItem* selected_item) const {
PreparedHtml html;
bool acc_displays_enclosures =
selected_item == nullptr || selected_item->getParentServiceRoot()->displaysEnclosures();
for (const Message& message : messages) {
bool is_plain = !TextFactory::couldBeHtml(message.m_contents);
@ -104,14 +106,17 @@ PreparedHtml TextBrowserViewer::prepareHtmlForMessage(const QList<Message>& mess
html.m_html += QSL("<div>");
// Add links to enclosures.
if (acc_displays_enclosures) {
for (const Enclosure& enc : message.m_enclosures) {
html.m_html += QSL("[%2] <a href=\"%1\">%1</a><br/>").arg(enc.m_url, enc.m_mimeType);
}
}
// Display enclosures which are pictures if user has it enabled.
auto first_enc_break_added = false;
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::DisplayEnclosuresInMessage)).toBool()) {
if (acc_displays_enclosures &&
qApp->settings()->value(GROUP(Messages), SETTING(Messages::DisplayEnclosuresInMessage)).toBool()) {
for (const Enclosure& enc : message.m_enclosures) {
if (enc.m_mimeType.startsWith(QSL("image/"))) {
if (!first_enc_break_added) {

View File

@ -230,11 +230,13 @@ PreparedHtml SkinFactory::generateHtmlOfArticles(const QList<Message>& messages,
QString enclosure_images;
bool is_plain = !TextFactory::couldBeHtml(message.m_contents);
if (root == nullptr || root->getParentServiceRoot()->displaysEnclosures()) {
for (const Enclosure& enclosure : message.m_enclosures) {
QString enc_url = QUrl::fromPercentEncoding(enclosure.m_url.toUtf8());
enclosures += skin.m_enclosureMarkup.arg(enc_url, QSL("&#129527;"), enclosure.m_mimeType);
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::DisplayEnclosuresInMessage)).toBool()) {
if (enclosure.m_mimeType.startsWith(QSL("image/")) &&
qApp->settings()->value(GROUP(Messages), SETTING(Messages::DisplayEnclosuresInMessage)).toBool()) {
// Add thumbnail image.
@ -244,6 +246,8 @@ PreparedHtml SkinFactory::generateHtmlOfArticles(const QList<Message>& messages,
forced_img_size <= 0 ? QString() : QString::number(forced_img_size));
}
}
}
}
QString msg_date =
qApp->settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()

View File

@ -323,6 +323,10 @@ bool ServiceRoot::wantsBaggedIdsOfExistingMessages() const {
return false;
}
bool ServiceRoot::displaysEnclosures() const {
return true;
}
void ServiceRoot::aboutToBeginFeedFetching(const QList<Feed*>& feeds,
const QHash<QString, QHash<BagOfMessages, QStringList>>& stated_messages,
const QHash<QString, QStringList>& tagged_messages) {

View File

@ -67,6 +67,7 @@ class ServiceRoot : public RootItem {
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual bool wantsBaggedIdsOfExistingMessages() const;
virtual bool displaysEnclosures() const;
virtual void aboutToBeginFeedFetching(const QList<Feed*>& feeds,
const QHash<QString, QHash<ServiceRoot::BagOfMessages, QStringList>>&
stated_messages,

View File

@ -547,6 +547,10 @@ bool GmailNetworkFactory::fillFullMessage(Message& msg, const QJsonObject& json,
msg.m_author = sanitizeEmailAuthor(headers[QSL("From")]);
msg.m_title = headers[QSL("Subject")];
// NOTE: Provide link to web-based GUI for the message.
msg.m_url = QSL("https://mail.google.com/mail/u/0/#all/%1").arg(msg.m_customId);
msg.m_createdFromFeed = true;
msg.m_created = TextFactory::parseDateTime(headers[QSL("Date")]);

View File

@ -245,3 +245,7 @@ void GmailServiceRoot::saveAllCachedData(bool ignore_errors) {
}
}
}
bool GmailServiceRoot::displaysEnclosures() const {
return false;
}

View File

@ -31,6 +31,7 @@ class GmailServiceRoot : public ServiceRoot, public CacheForServiceRoot {
virtual QString code() const;
virtual QString additionalTooltip() const;
virtual void saveAllCachedData(bool ignore_errors);
virtual bool displaysEnclosures() const;
virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data);
virtual QList<Message> obtainNewMessages(Feed* feed,