aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Rusakov <Kitsune-Ral@users.sf.net>2022-01-02 05:28:24 +0100
committerAlexey Rusakov <Kitsune-Ral@users.sf.net>2022-01-02 05:28:24 +0100
commitd516280a2b38ccb060e4f7502b873e19b1559ed1 (patch)
treeb995becf2cb8d002ac3fa4d68c69a69a8f26fdcc
parent545f9084bacead9f02ba6df609822be4672b7952 (diff)
parent2dee2bf4f0b2bd6615866644b2df9460da6babbb (diff)
downloadlibquotient-d516280a2b38ccb060e4f7502b873e19b1559ed1.tar.gz
libquotient-d516280a2b38ccb060e4f7502b873e19b1559ed1.zip
Manage symbols visibility for dynamic linking
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--CMakeLists.txt13
-rw-r--r--gtad/operation.h.mustache2
-rw-r--r--lib/accountregistry.h4
-rw-r--r--lib/avatar.h4
-rw-r--r--lib/connection.h2
-rw-r--r--lib/converters.h6
-rw-r--r--lib/csapi/account-data.h8
-rw-r--r--lib/csapi/admin.h2
-rw-r--r--lib/csapi/administrative_contact.h16
-rw-r--r--lib/csapi/appservice_room_directory.h3
-rw-r--r--lib/csapi/banning.h4
-rw-r--r--lib/csapi/capabilities.h2
-rw-r--r--lib/csapi/content-repo.h12
-rw-r--r--lib/csapi/create_room.h2
-rw-r--r--lib/csapi/cross_signing.h4
-rw-r--r--lib/csapi/device_management.h10
-rw-r--r--lib/csapi/directory.h8
-rw-r--r--lib/csapi/event_context.h2
-rw-r--r--lib/csapi/filter.h4
-rw-r--r--lib/csapi/inviting.h2
-rw-r--r--lib/csapi/joining.h4
-rw-r--r--lib/csapi/keys.h8
-rw-r--r--lib/csapi/kicking.h2
-rw-r--r--lib/csapi/knocking.h2
-rw-r--r--lib/csapi/leaving.h4
-rw-r--r--lib/csapi/list_joined_rooms.h2
-rw-r--r--lib/csapi/list_public_rooms.h8
-rw-r--r--lib/csapi/login.h4
-rw-r--r--lib/csapi/logout.h4
-rw-r--r--lib/csapi/message_pagination.h2
-rw-r--r--lib/csapi/notifications.h2
-rw-r--r--lib/csapi/openid.h2
-rw-r--r--lib/csapi/peeking_events.h2
-rw-r--r--lib/csapi/presence.h4
-rw-r--r--lib/csapi/profile.h10
-rw-r--r--lib/csapi/pusher.h4
-rw-r--r--lib/csapi/pushrules.h16
-rw-r--r--lib/csapi/read_markers.h2
-rw-r--r--lib/csapi/receipts.h2
-rw-r--r--lib/csapi/redaction.h2
-rw-r--r--lib/csapi/registration.h16
-rw-r--r--lib/csapi/report_content.h2
-rw-r--r--lib/csapi/room_send.h2
-rw-r--r--lib/csapi/room_state.h2
-rw-r--r--lib/csapi/room_upgrades.h2
-rw-r--r--lib/csapi/rooms.h10
-rw-r--r--lib/csapi/search.h2
-rw-r--r--lib/csapi/sso_login_redirect.h4
-rw-r--r--lib/csapi/tags.h6
-rw-r--r--lib/csapi/third_party_lookup.h12
-rw-r--r--lib/csapi/third_party_membership.h2
-rw-r--r--lib/csapi/to_device.h2
-rw-r--r--lib/csapi/typing.h2
-rw-r--r--lib/csapi/users.h2
-rw-r--r--lib/csapi/versions.h2
-rw-r--r--lib/csapi/voip.h2
-rw-r--r--lib/csapi/wellknown.h2
-rw-r--r--lib/csapi/whoami.h2
-rw-r--r--lib/eventitem.cpp4
-rw-r--r--lib/eventitem.h9
-rw-r--r--lib/events/accountdataevents.h2
-rw-r--r--lib/events/callanswerevent.h3
-rw-r--r--lib/events/callhangupevent.h2
-rw-r--r--lib/events/callinviteevent.h2
-rw-r--r--lib/events/directchatevent.h2
-rw-r--r--lib/events/encryptedevent.h2
-rw-r--r--lib/events/encryptionevent.h5
-rw-r--r--lib/events/event.cpp20
-rw-r--r--lib/events/event.h225
-rw-r--r--lib/events/eventcontent.h19
-rw-r--r--lib/events/reactionevent.h6
-rw-r--r--lib/events/receiptevent.h2
-rw-r--r--lib/events/roomavatarevent.h3
-rw-r--r--lib/events/roomcreateevent.h2
-rw-r--r--lib/events/roomevent.h6
-rw-r--r--lib/events/roomkeyevent.h2
-rw-r--r--lib/events/roommemberevent.h5
-rw-r--r--lib/events/roommessageevent.h8
-rw-r--r--lib/events/roompowerlevelsevent.h8
-rw-r--r--lib/events/roomtombstoneevent.h2
-rw-r--r--lib/events/simplestateevents.h3
-rw-r--r--lib/events/stateevent.h4
-rw-r--r--lib/events/stickerevent.h2
-rw-r--r--lib/events/typingevent.h2
-rw-r--r--lib/eventstats.h4
-rw-r--r--lib/jobs/basejob.h4
-rw-r--r--lib/jobs/downloadfilejob.cpp2
-rw-r--r--lib/jobs/downloadfilejob.h3
-rw-r--r--lib/jobs/mediathumbnailjob.h2
-rw-r--r--lib/jobs/requestdata.h4
-rw-r--r--lib/mxcreply.cpp2
-rw-r--r--lib/mxcreply.h6
-rw-r--r--lib/networkaccessmanager.h4
-rw-r--r--lib/networksettings.h2
-rw-r--r--lib/quotient_common.h17
-rw-r--r--lib/quotient_export.h23
-rw-r--r--lib/room.h8
-rw-r--r--lib/settings.h8
-rw-r--r--lib/ssosession.h4
-rw-r--r--lib/syncdata.h2
-rw-r--r--lib/uri.h2
-rw-r--r--lib/uriresolver.h6
-rw-r--r--lib/user.h3
-rw-r--r--lib/util.h22
-rw-r--r--quotest/CMakeLists.txt5
-rw-r--r--quotest/quotest.cpp57
107 files changed, 457 insertions, 359 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e56ea26e..35a5c6f9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -105,8 +105,10 @@ jobs:
fi
echo "QUOTEST_ORIGIN=$VERSION @ ${{ runner.os }}/${{ matrix.compiler }}" >>$GITHUB_ENV
+ # Build libQuotient as a shared library across platforms but also
+ # check the static configuration somewhere
CMAKE_ARGS="-G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo \
- -DBUILD_SHARED_LIBS=false \
+ -DBUILD_SHARED_LIBS=${{ !matrix.sonar && runner.os == 'Linux' }} \
-DCMAKE_INSTALL_PREFIX=~/.local \
-DCMAKE_PREFIX_PATH=~/.local \
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON"
@@ -120,6 +122,7 @@ jobs:
if [[ '${{ runner.os }}' != 'Windows' ]]; then
BIN_DIR=/bin
+ echo "LIB_PATH=$HOME/.local/lib" >>$GITHUB_ENV
fi
echo "BIN_DIR=$BIN_DIR" >>$GITHUB_ENV
echo "~/.local$BIN_DIR" >>$GITHUB_PATH
@@ -203,6 +206,7 @@ jobs:
run: |
ctest --test-dir $BUILD_PATH --output-on-failure
[[ -z "$TEST_USER" ]] || \
+ LD_LIBRARY_PATH=$LIB_PATH \
$VALGRIND quotest "$TEST_USER" "$TEST_PWD" quotest-gha '#quotest:matrix.org' "$QUOTEST_ORIGIN"
timeout-minutes: 4 # quotest is supposed to finish within 3 minutes, actually
diff --git a/CMakeLists.txt b/CMakeLists.txt
index adb5be7b..c889cf13 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,7 +40,7 @@ if (MSVC)
/wd4710 /wd4774 /wd4820 /wd4946 /wd5026 /wd5027)
else()
foreach (FLAG Wall Wpedantic Wextra Werror=return-type Wno-unused-parameter
- Wno-gnu-zero-variadic-macro-arguments fvisibility-inlines-hidden)
+ Wno-gnu-zero-variadic-macro-arguments)
CHECK_CXX_COMPILER_FLAG("-${FLAG}" COMPILER_${FLAG}_SUPPORTED)
if ( COMPILER_${FLAG}_SUPPORTED AND
NOT CMAKE_CXX_FLAGS MATCHES "(^| )-?${FLAG}($| )")
@@ -125,6 +125,7 @@ endif ()
# Set up source files
list(APPEND lib_SRCS
lib/quotient_common.h
+ lib/quotient_export.h
lib/function_traits.h lib/function_traits.cpp
lib/networkaccessmanager.h lib/networkaccessmanager.cpp
lib/connectiondata.h lib/connectiondata.cpp
@@ -253,6 +254,12 @@ file(GLOB_RECURSE api_ALL_SRCS CONFIGURE_DEPENDS
${FULL_CSAPI_DIR}/*.* lib/${ASAPI_DEF_DIR}/*.* lib/${ISAPI_DEF_DIR}/*.*)
add_library(${PROJECT_NAME} ${lib_SRCS} ${api_ALL_SRCS})
+# Set BUILDING_SHARED_QUOTIENT if building as a shared library
+target_compile_definitions(${PROJECT_NAME} PRIVATE
+ $<$<STREQUAL:$<TARGET_PROPERTY:${PROJECT_NAME},TYPE>,SHARED_LIBRARY>:BUILDING_SHARED_QUOTIENT>)
+# Set QUOTIENT_STATIC in a static library setting
+target_compile_definitions(${PROJECT_NAME} PUBLIC
+ $<$<STREQUAL:$<TARGET_PROPERTY:${PROJECT_NAME},TYPE>,STATIC_LIBRARY>:QUOTIENT_STATIC>)
target_compile_definitions(${PROJECT_NAME} PRIVATE QT_NO_JAVA_STYLE_ITERATORS QT_NO_URL_CAST_FROM_STRING QT_NO_CAST_TO_ASCII)
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_NAME}_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
@@ -264,6 +271,8 @@ endif()
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 20
CXX_EXTENSIONS OFF
+ VISIBILITY_INLINES_HIDDEN ON
+ CXX_VISIBILITY_PRESET hidden
VERSION "${PROJECT_VERSION}"
SOVERSION ${API_VERSION}
INTERFACE_${PROJECT_NAME}_MAJOR_VERSION ${API_VERSION}
@@ -307,8 +316,6 @@ endif()
# Configure installation
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${${PROJECT_NAME}_INSTALL_INCLUDEDIR}
)
install(DIRECTORY lib/ DESTINATION ${${PROJECT_NAME}_INSTALL_INCLUDEDIR}
diff --git a/gtad/operation.h.mustache b/gtad/operation.h.mustache
index f91dc66c..063f0bbd 100644
--- a/gtad/operation.h.mustache
+++ b/gtad/operation.h.mustache
@@ -16,7 +16,7 @@ namespace Quotient {
/*!{{>docCommentSummary}}{{#description}}
* {{_}}{{/description}}
*/
-class {{camelCaseOperationId}}Job : public BaseJob {
+class QUOTIENT_API {{camelCaseOperationId}}Job : public BaseJob {
public:
{{#models}}
// Inner data structures
diff --git a/lib/accountregistry.h b/lib/accountregistry.h
index 5efda459..f7a864df 100644
--- a/lib/accountregistry.h
+++ b/lib/accountregistry.h
@@ -4,6 +4,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtCore/QObject>
#include <QtCore/QList>
#include <QtCore/QAbstractListModel>
@@ -11,7 +13,7 @@
namespace Quotient {
class Connection;
-class AccountRegistry : public QAbstractListModel {
+class QUOTIENT_API AccountRegistry : public QAbstractListModel {
Q_OBJECT
public:
enum EventRoles {
diff --git a/lib/avatar.h b/lib/avatar.h
index d4634aea..93f43948 100644
--- a/lib/avatar.h
+++ b/lib/avatar.h
@@ -3,6 +3,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtCore/QUrl>
#include <QtGui/QIcon>
@@ -12,7 +14,7 @@
namespace Quotient {
class Connection;
-class Avatar {
+class QUOTIENT_API Avatar {
public:
explicit Avatar();
explicit Avatar(QUrl url);
diff --git a/lib/connection.h b/lib/connection.h
index 45abb8ed..23062664 100644
--- a/lib/connection.h
+++ b/lib/connection.h
@@ -105,7 +105,7 @@ using DirectChatsMap = QMultiHash<const User*, QString>;
using DirectChatUsersMap = QMultiHash<QString, User*>;
using IgnoredUsersList = IgnoredUsersEvent::content_type;
-class Connection : public QObject {
+class QUOTIENT_API Connection : public QObject {
Q_OBJECT
Q_PROPERTY(User* localUser READ user NOTIFY stateChanged)
diff --git a/lib/converters.h b/lib/converters.h
index 9c3d5749..a6028f1b 100644
--- a/lib/converters.h
+++ b/lib/converters.h
@@ -183,7 +183,7 @@ struct JsonConverter<QUrl> {
};
template <>
-struct JsonConverter<QVariant> {
+struct QUOTIENT_API JsonConverter<QVariant> {
static QJsonValue dump(const QVariant& v);
static QVariant load(const QJsonValue& jv);
};
@@ -281,9 +281,9 @@ template <typename T>
struct JsonObjectConverter<QHash<QString, T>>
: public HashMapFromJson<QHash<QString, T>> {};
-QJsonObject toJson(const QVariantHash& vh);
+QJsonObject QUOTIENT_API toJson(const QVariantHash& vh);
template <>
-QVariantHash fromJson(const QJsonValue& jv);
+QVariantHash QUOTIENT_API fromJson(const QJsonValue& jv);
// Conditional insertion into a QJsonObject
diff --git a/lib/csapi/account-data.h b/lib/csapi/account-data.h
index 0c760e80..5140d340 100644
--- a/lib/csapi/account-data.h
+++ b/lib/csapi/account-data.h
@@ -14,7 +14,7 @@ namespace Quotient {
* that set the account_data. The config will be synced to clients in the
* top-level `account_data`.
*/
-class SetAccountDataJob : public BaseJob {
+class QUOTIENT_API SetAccountDataJob : public BaseJob {
public:
/*! \brief Set some account_data for the user.
*
@@ -38,7 +38,7 @@ public:
* Get some account_data for the client. This config is only visible to the user
* that set the account_data.
*/
-class GetAccountDataJob : public BaseJob {
+class QUOTIENT_API GetAccountDataJob : public BaseJob {
public:
/*! \brief Get some account_data for the user.
*
@@ -67,7 +67,7 @@ public:
* visible to the user that set the account_data. The config will be synced to
* clients in the per-room `account_data`.
*/
-class SetAccountDataPerRoomJob : public BaseJob {
+class QUOTIENT_API SetAccountDataPerRoomJob : public BaseJob {
public:
/*! \brief Set some account_data for the user.
*
@@ -95,7 +95,7 @@ public:
* Get some account_data for the client on a given room. This config is only
* visible to the user that set the account_data.
*/
-class GetAccountDataPerRoomJob : public BaseJob {
+class QUOTIENT_API GetAccountDataPerRoomJob : public BaseJob {
public:
/*! \brief Get some account_data for the user.
*
diff --git a/lib/csapi/admin.h b/lib/csapi/admin.h
index 570bf24a..c53ddd7e 100644
--- a/lib/csapi/admin.h
+++ b/lib/csapi/admin.h
@@ -16,7 +16,7 @@ namespace Quotient {
* up, or by a server admin. Server-local administrator privileges are not
* specified in this document.
*/
-class GetWhoIsJob : public BaseJob {
+class QUOTIENT_API GetWhoIsJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/administrative_contact.h b/lib/csapi/administrative_contact.h
index e436971d..e636b12a 100644
--- a/lib/csapi/administrative_contact.h
+++ b/lib/csapi/administrative_contact.h
@@ -24,7 +24,7 @@ namespace Quotient {
* Identifiers in this list may be used by the homeserver as, for example,
* identifiers that it will accept to reset the user's account password.
*/
-class GetAccount3PIDsJob : public BaseJob {
+class QUOTIENT_API GetAccount3PIDsJob : public BaseJob {
public:
// Inner data structures
@@ -102,7 +102,7 @@ struct JsonObjectConverter<GetAccount3PIDsJob::ThirdPartyIdentifier> {
* This results in this endpoint being an equivalent to `/3pid/bind` rather
* than dual-purpose.
*/
-class Post3PIDsJob : public BaseJob {
+class QUOTIENT_API Post3PIDsJob : public BaseJob {
public:
// Inner data structures
@@ -154,7 +154,7 @@ struct JsonObjectConverter<Post3PIDsJob::ThreePidCredentials> {
* Homeservers should prevent the caller from adding a 3PID to their account if
* it has already been added to another user's account on the homeserver.
*/
-class Add3PIDJob : public BaseJob {
+class QUOTIENT_API Add3PIDJob : public BaseJob {
public:
/*! \brief Adds contact information to the user's account.
*
@@ -182,7 +182,7 @@ public:
*
* Homeservers should track successful binds so they can be unbound later.
*/
-class Bind3PIDJob : public BaseJob {
+class QUOTIENT_API Bind3PIDJob : public BaseJob {
public:
/*! \brief Binds a 3PID to the user's account through an Identity Service.
*
@@ -211,7 +211,7 @@ public:
* parameter because the homeserver is expected to sign the request to the
* identity server instead.
*/
-class Delete3pidFromAccountJob : public BaseJob {
+class QUOTIENT_API Delete3pidFromAccountJob : public BaseJob {
public:
/*! \brief Deletes a third party identifier from the user's account
*
@@ -254,7 +254,7 @@ public:
* parameter because the homeserver is expected to sign the request to the
* identity server instead.
*/
-class Unbind3pidFromAccountJob : public BaseJob {
+class QUOTIENT_API Unbind3pidFromAccountJob : public BaseJob {
public:
/*! \brief Removes a user's third party identifier from an identity server.
*
@@ -300,7 +300,7 @@ public:
* the email itself, either by sending a validation email itself or by using
* a service it has control over.
*/
-class RequestTokenTo3PIDEmailJob : public BaseJob {
+class QUOTIENT_API RequestTokenTo3PIDEmailJob : public BaseJob {
public:
/*! \brief Begins the validation process for an email address for
* association with the user's account.
@@ -342,7 +342,7 @@ public:
* the phone number itself, either by sending a validation message itself or by
* using a service it has control over.
*/
-class RequestTokenTo3PIDMSISDNJob : public BaseJob {
+class QUOTIENT_API RequestTokenTo3PIDMSISDNJob : public BaseJob {
public:
/*! \brief Begins the validation process for a phone number for association
* with the user's account.
diff --git a/lib/csapi/appservice_room_directory.h b/lib/csapi/appservice_room_directory.h
index 56a69592..6b2801ca 100644
--- a/lib/csapi/appservice_room_directory.h
+++ b/lib/csapi/appservice_room_directory.h
@@ -21,7 +21,8 @@ namespace Quotient {
* instead of a typical client's access_token. This API cannot be invoked by
* users who are not identified as application services.
*/
-class UpdateAppserviceRoomDirectoryVisibilityJob : public BaseJob {
+class QUOTIENT_API UpdateAppserviceRoomDirectoryVisibilityJob
+ : public BaseJob {
public:
/*! \brief Updates a room's visibility in the application service's room
* directory.
diff --git a/lib/csapi/banning.h b/lib/csapi/banning.h
index 7a9697d3..e4c60ce3 100644
--- a/lib/csapi/banning.h
+++ b/lib/csapi/banning.h
@@ -18,7 +18,7 @@ namespace Quotient {
* The caller must have the required power level in order to perform this
* operation.
*/
-class BanJob : public BaseJob {
+class QUOTIENT_API BanJob : public BaseJob {
public:
/*! \brief Ban a user in the room.
*
@@ -46,7 +46,7 @@ public:
* The caller must have the required power level in order to perform this
* operation.
*/
-class UnbanJob : public BaseJob {
+class QUOTIENT_API UnbanJob : public BaseJob {
public:
/*! \brief Unban a user from the room.
*
diff --git a/lib/csapi/capabilities.h b/lib/csapi/capabilities.h
index da50c8c1..81b47cd4 100644
--- a/lib/csapi/capabilities.h
+++ b/lib/csapi/capabilities.h
@@ -13,7 +13,7 @@ namespace Quotient {
* Gets information about the server's supported feature set
* and other relevant capabilities.
*/
-class GetCapabilitiesJob : public BaseJob {
+class QUOTIENT_API GetCapabilitiesJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/content-repo.h b/lib/csapi/content-repo.h
index 28409f5c..511db985 100644
--- a/lib/csapi/content-repo.h
+++ b/lib/csapi/content-repo.h
@@ -14,7 +14,7 @@ namespace Quotient {
/*! \brief Upload some content to the content repository.
*
*/
-class UploadContentJob : public BaseJob {
+class QUOTIENT_API UploadContentJob : public BaseJob {
public:
/*! \brief Upload some content to the content repository.
*
@@ -40,7 +40,7 @@ public:
/*! \brief Download content from the content repository.
*
*/
-class GetContentJob : public BaseJob {
+class QUOTIENT_API GetContentJob : public BaseJob {
public:
/*! \brief Download content from the content repository.
*
@@ -87,7 +87,7 @@ public:
* the previous endpoint) but replace the target file name with the one
* provided by the caller.
*/
-class GetContentOverrideNameJob : public BaseJob {
+class QUOTIENT_API GetContentOverrideNameJob : public BaseJob {
public:
/*! \brief Download content from the content repository overriding the file
* name
@@ -142,7 +142,7 @@ public:
* See the [Thumbnails](/client-server-api/#thumbnails) section for more
* information.
*/
-class GetContentThumbnailJob : public BaseJob {
+class QUOTIENT_API GetContentThumbnailJob : public BaseJob {
public:
/*! \brief Download a thumbnail of content from the content repository
*
@@ -204,7 +204,7 @@ public:
* do not want to share with the homeserver, and this can mean that the URLs
* being shared should also not be shared with the homeserver.
*/
-class GetUrlPreviewJob : public BaseJob {
+class QUOTIENT_API GetUrlPreviewJob : public BaseJob {
public:
/*! \brief Get information about a URL for a client
*
@@ -252,7 +252,7 @@ public:
* content repository APIs, for example, proxies may enforce a lower upload size
* limit than is advertised by the server on this endpoint.
*/
-class GetConfigJob : public BaseJob {
+class QUOTIENT_API GetConfigJob : public BaseJob {
public:
/// Get the configuration for the content repository.
explicit GetConfigJob();
diff --git a/lib/csapi/create_room.h b/lib/csapi/create_room.h
index 81dfbffc..7d566057 100644
--- a/lib/csapi/create_room.h
+++ b/lib/csapi/create_room.h
@@ -53,7 +53,7 @@ namespace Quotient {
* requesting user as the creator, alongside other keys provided in the
* `creation_content`.
*/
-class CreateRoomJob : public BaseJob {
+class QUOTIENT_API CreateRoomJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/cross_signing.h b/lib/csapi/cross_signing.h
index 2ab65e06..617b61d1 100644
--- a/lib/csapi/cross_signing.h
+++ b/lib/csapi/cross_signing.h
@@ -17,7 +17,7 @@ namespace Quotient {
* This API endpoint uses the [User-Interactive Authentication
* API](/client-server-api/#user-interactive-authentication-api).
*/
-class UploadCrossSigningKeysJob : public BaseJob {
+class QUOTIENT_API UploadCrossSigningKeysJob : public BaseJob {
public:
/*! \brief Upload cross-signing keys.
*
@@ -47,7 +47,7 @@ public:
* Publishes cross-signing signatures for the user. The request body is a
* map from user ID to key ID to signed JSON object.
*/
-class UploadCrossSigningSignaturesJob : public BaseJob {
+class QUOTIENT_API UploadCrossSigningSignaturesJob : public BaseJob {
public:
/*! \brief Upload cross-signing signatures.
*
diff --git a/lib/csapi/device_management.h b/lib/csapi/device_management.h
index 7fb69873..430d2132 100644
--- a/lib/csapi/device_management.h
+++ b/lib/csapi/device_management.h
@@ -15,7 +15,7 @@ namespace Quotient {
*
* Gets information about all devices for the current user.
*/
-class GetDevicesJob : public BaseJob {
+class QUOTIENT_API GetDevicesJob : public BaseJob {
public:
/// List registered devices for the current user
explicit GetDevicesJob();
@@ -40,7 +40,7 @@ public:
*
* Gets information on a single device, by device id.
*/
-class GetDeviceJob : public BaseJob {
+class QUOTIENT_API GetDeviceJob : public BaseJob {
public:
/*! \brief Get a single device
*
@@ -66,7 +66,7 @@ public:
*
* Updates the metadata on the given device.
*/
-class UpdateDeviceJob : public BaseJob {
+class QUOTIENT_API UpdateDeviceJob : public BaseJob {
public:
/*! \brief Update a device
*
@@ -88,7 +88,7 @@ public:
*
* Deletes the given device, and invalidates any access token associated with it.
*/
-class DeleteDeviceJob : public BaseJob {
+class QUOTIENT_API DeleteDeviceJob : public BaseJob {
public:
/*! \brief Delete a device
*
@@ -111,7 +111,7 @@ public:
* Deletes the given devices, and invalidates any access token associated with
* them.
*/
-class DeleteDevicesJob : public BaseJob {
+class QUOTIENT_API DeleteDevicesJob : public BaseJob {
public:
/*! \brief Bulk deletion of devices
*
diff --git a/lib/csapi/directory.h b/lib/csapi/directory.h
index 93a31595..0bd13a76 100644
--- a/lib/csapi/directory.h
+++ b/lib/csapi/directory.h
@@ -11,7 +11,7 @@ namespace Quotient {
/*! \brief Create a new mapping from room alias to room ID.
*
*/
-class SetRoomAliasJob : public BaseJob {
+class QUOTIENT_API SetRoomAliasJob : public BaseJob {
public:
/*! \brief Create a new mapping from room alias to room ID.
*
@@ -32,7 +32,7 @@ public:
* domain part of the alias does not correspond to the server's own
* domain.
*/
-class GetRoomIdByAliasJob : public BaseJob {
+class QUOTIENT_API GetRoomIdByAliasJob : public BaseJob {
public:
/*! \brief Get the room ID corresponding to this room alias.
*
@@ -76,7 +76,7 @@ public:
* return a successful response even if the user does not have permission to
* update the `m.room.canonical_alias` event.
*/
-class DeleteRoomAliasJob : public BaseJob {
+class QUOTIENT_API DeleteRoomAliasJob : public BaseJob {
public:
/*! \brief Remove a mapping of room alias to room ID.
*
@@ -112,7 +112,7 @@ public:
* as they are not curated, unlike those listed in the `m.room.canonical_alias`
* state event.
*/
-class GetLocalAliasesJob : public BaseJob {
+class QUOTIENT_API GetLocalAliasesJob : public BaseJob {
public:
/*! \brief Get a list of local aliases on a given room.
*
diff --git a/lib/csapi/event_context.h b/lib/csapi/event_context.h
index 4e50edf3..662b976b 100644
--- a/lib/csapi/event_context.h
+++ b/lib/csapi/event_context.h
@@ -19,7 +19,7 @@ namespace Quotient {
* [Lazy-loading room members](/client-server-api/#lazy-loading-room-members)
* for more information.
*/
-class GetEventContextJob : public BaseJob {
+class QUOTIENT_API GetEventContextJob : public BaseJob {
public:
/*! \brief Get events and state around the specified event.
*
diff --git a/lib/csapi/filter.h b/lib/csapi/filter.h
index 01bec36b..9518a461 100644
--- a/lib/csapi/filter.h
+++ b/lib/csapi/filter.h
@@ -16,7 +16,7 @@ namespace Quotient {
* Returns a filter ID that may be used in future requests to
* restrict which events are returned to the client.
*/
-class DefineFilterJob : public BaseJob {
+class QUOTIENT_API DefineFilterJob : public BaseJob {
public:
/*! \brief Upload a new filter.
*
@@ -41,7 +41,7 @@ public:
/*! \brief Download a filter
*
*/
-class GetFilterJob : public BaseJob {
+class QUOTIENT_API GetFilterJob : public BaseJob {
public:
/*! \brief Download a filter
*
diff --git a/lib/csapi/inviting.h b/lib/csapi/inviting.h
index eb13cc95..21e6cb74 100644
--- a/lib/csapi/inviting.h
+++ b/lib/csapi/inviting.h
@@ -26,7 +26,7 @@ namespace Quotient {
* If the user was invited to the room, the homeserver will append a
* `m.room.member` event to the room.
*/
-class InviteUserJob : public BaseJob {
+class QUOTIENT_API InviteUserJob : public BaseJob {
public:
/*! \brief Invite a user to participate in a particular room.
*
diff --git a/lib/csapi/joining.h b/lib/csapi/joining.h
index d0199b11..f64152f7 100644
--- a/lib/csapi/joining.h
+++ b/lib/csapi/joining.h
@@ -25,7 +25,7 @@ namespace Quotient {
* [`/initialSync`](/client-server-api/#get_matrixclientr0initialsync) and
* [`/sync`](/client-server-api/#get_matrixclientr0sync) APIs.
*/
-class JoinRoomByIdJob : public BaseJob {
+class QUOTIENT_API JoinRoomByIdJob : public BaseJob {
public:
/*! \brief Start the requesting user participating in a particular room.
*
@@ -67,7 +67,7 @@ public:
* [`/initialSync`](/client-server-api/#get_matrixclientr0initialsync) and
* [`/sync`](/client-server-api/#get_matrixclientr0sync) APIs.
*/
-class JoinRoomJob : public BaseJob {
+class QUOTIENT_API JoinRoomJob : public BaseJob {
public:
/*! \brief Start the requesting user participating in a particular room.
*
diff --git a/lib/csapi/keys.h b/lib/csapi/keys.h
index 7db09e8d..ce1ca9ed 100644
--- a/lib/csapi/keys.h
+++ b/lib/csapi/keys.h
@@ -15,7 +15,7 @@ namespace Quotient {
*
* Publishes end-to-end encryption keys for the device.
*/
-class UploadKeysJob : public BaseJob {
+class QUOTIENT_API UploadKeysJob : public BaseJob {
public:
/*! \brief Upload end-to-end encryption keys.
*
@@ -48,7 +48,7 @@ public:
*
* Returns the current devices and identity keys for the given users.
*/
-class QueryKeysJob : public BaseJob {
+class QUOTIENT_API QueryKeysJob : public BaseJob {
public:
// Inner data structures
@@ -172,7 +172,7 @@ struct JsonObjectConverter<QueryKeysJob::DeviceInformation> {
*
* Claims one-time keys for use in pre-key messages.
*/
-class ClaimKeysJob : public BaseJob {
+class QUOTIENT_API ClaimKeysJob : public BaseJob {
public:
/*! \brief Claim one-time encryption keys.
*
@@ -226,7 +226,7 @@ public:
* * added new device identity keys or removed an existing device with
* identity keys, between `from` and `to`.
*/
-class GetKeysChangesJob : public BaseJob {
+class QUOTIENT_API GetKeysChangesJob : public BaseJob {
public:
/*! \brief Query users with recent device key updates.
*
diff --git a/lib/csapi/kicking.h b/lib/csapi/kicking.h
index 11018368..6ac106e2 100644
--- a/lib/csapi/kicking.h
+++ b/lib/csapi/kicking.h
@@ -20,7 +20,7 @@ namespace Quotient {
* directly adjust the target member's state by making a request to
* `/rooms/<room id>/state/m.room.member/<user id>`.
*/
-class KickJob : public BaseJob {
+class QUOTIENT_API KickJob : public BaseJob {
public:
/*! \brief Kick a user from the room.
*
diff --git a/lib/csapi/knocking.h b/lib/csapi/knocking.h
index 1108cb64..e3645b59 100644
--- a/lib/csapi/knocking.h
+++ b/lib/csapi/knocking.h
@@ -27,7 +27,7 @@ namespace Quotient {
* The knock will appear as an entry in the response of the
* [`/sync`](/client-server-api/#get_matrixclientr0sync) API.
*/
-class KnockRoomJob : public BaseJob {
+class QUOTIENT_API KnockRoomJob : public BaseJob {
public:
/*! \brief Knock on a room, requesting permission to join.
*
diff --git a/lib/csapi/leaving.h b/lib/csapi/leaving.h
index 2e402d16..19cac3f0 100644
--- a/lib/csapi/leaving.h
+++ b/lib/csapi/leaving.h
@@ -22,7 +22,7 @@ namespace Quotient {
* The user will still be allowed to retrieve history from the room which
* they were previously allowed to see.
*/
-class LeaveRoomJob : public BaseJob {
+class QUOTIENT_API LeaveRoomJob : public BaseJob {
public:
/*! \brief Stop the requesting user participating in a particular room.
*
@@ -48,7 +48,7 @@ public:
* If the user is currently joined to the room, they must leave the room
* before calling this API.
*/
-class ForgetRoomJob : public BaseJob {
+class QUOTIENT_API ForgetRoomJob : public BaseJob {
public:
/*! \brief Stop the requesting user remembering about a particular room.
*
diff --git a/lib/csapi/list_joined_rooms.h b/lib/csapi/list_joined_rooms.h
index 59a24a49..aea68afd 100644
--- a/lib/csapi/list_joined_rooms.h
+++ b/lib/csapi/list_joined_rooms.h
@@ -12,7 +12,7 @@ namespace Quotient {
*
* This API returns a list of the user's current rooms.
*/
-class GetJoinedRoomsJob : public BaseJob {
+class QUOTIENT_API GetJoinedRoomsJob : public BaseJob {
public:
/// Lists the user's current rooms.
explicit GetJoinedRoomsJob();
diff --git a/lib/csapi/list_public_rooms.h b/lib/csapi/list_public_rooms.h
index 963c8b56..e1f03db7 100644
--- a/lib/csapi/list_public_rooms.h
+++ b/lib/csapi/list_public_rooms.h
@@ -14,7 +14,7 @@ namespace Quotient {
*
* Gets the visibility of a given room on the server's public room directory.
*/
-class GetRoomVisibilityOnDirectoryJob : public BaseJob {
+class QUOTIENT_API GetRoomVisibilityOnDirectoryJob : public BaseJob {
public:
/*! \brief Gets the visibility of a room in the directory
*
@@ -48,7 +48,7 @@ public:
* here, for instance that room visibility can only be changed by
* the room creator or a server administrator.
*/
-class SetRoomVisibilityOnDirectoryJob : public BaseJob {
+class QUOTIENT_API SetRoomVisibilityOnDirectoryJob : public BaseJob {
public:
/*! \brief Sets the visibility of a room in the room directory
*
@@ -70,7 +70,7 @@ public:
* This API returns paginated responses. The rooms are ordered by the number
* of joined members, with the largest rooms first.
*/
-class GetPublicRoomsJob : public BaseJob {
+class QUOTIENT_API GetPublicRoomsJob : public BaseJob {
public:
/*! \brief Lists the public rooms on the server.
*
@@ -133,7 +133,7 @@ public:
* This API returns paginated responses. The rooms are ordered by the number
* of joined members, with the largest rooms first.
*/
-class QueryPublicRoomsJob : public BaseJob {
+class QUOTIENT_API QueryPublicRoomsJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/login.h b/lib/csapi/login.h
index b35db1eb..ce6951eb 100644
--- a/lib/csapi/login.h
+++ b/lib/csapi/login.h
@@ -16,7 +16,7 @@ namespace Quotient {
* Gets the homeserver's supported login types to authenticate users. Clients
* should pick one of these and supply it as the `type` when logging in.
*/
-class GetLoginFlowsJob : public BaseJob {
+class QUOTIENT_API GetLoginFlowsJob : public BaseJob {
public:
// Inner data structures
@@ -73,7 +73,7 @@ struct JsonObjectConverter<GetLoginFlowsJob::LoginFlow> {
* [Relationship between access tokens and
* devices](/client-server-api/#relationship-between-access-tokens-and-devices).
*/
-class LoginJob : public BaseJob {
+class QUOTIENT_API LoginJob : public BaseJob {
public:
/*! \brief Authenticates the user.
*
diff --git a/lib/csapi/logout.h b/lib/csapi/logout.h
index 2e4c2692..3f1ac7fa 100644
--- a/lib/csapi/logout.h
+++ b/lib/csapi/logout.h
@@ -15,7 +15,7 @@ namespace Quotient {
* [Device keys](/client-server-api/#device-keys) for the device are deleted
* alongside the device.
*/
-class LogoutJob : public BaseJob {
+class QUOTIENT_API LogoutJob : public BaseJob {
public:
/// Invalidates a user access token
explicit LogoutJob();
@@ -44,7 +44,7 @@ public:
* used in the request, and therefore the attacker is unable to take over the
* account in this way.
*/
-class LogoutAllJob : public BaseJob {
+class QUOTIENT_API LogoutAllJob : public BaseJob {
public:
/// Invalidates all access tokens for a user
explicit LogoutAllJob();
diff --git a/lib/csapi/message_pagination.h b/lib/csapi/message_pagination.h
index 363e4d99..8c18f104 100644
--- a/lib/csapi/message_pagination.h
+++ b/lib/csapi/message_pagination.h
@@ -18,7 +18,7 @@ namespace Quotient {
* [Lazy-loading room members](/client-server-api/#lazy-loading-room-members)
* for more information.
*/
-class GetRoomEventsJob : public BaseJob {
+class QUOTIENT_API GetRoomEventsJob : public BaseJob {
public:
/*! \brief Get a list of events for this room
*
diff --git a/lib/csapi/notifications.h b/lib/csapi/notifications.h
index 0c38fe6b..23211758 100644
--- a/lib/csapi/notifications.h
+++ b/lib/csapi/notifications.h
@@ -14,7 +14,7 @@ namespace Quotient {
* This API is used to paginate through the list of events that the
* user has been, or would have been notified about.
*/
-class GetNotificationsJob : public BaseJob {
+class QUOTIENT_API GetNotificationsJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/openid.h b/lib/csapi/openid.h
index 0be39c8c..773b6011 100644
--- a/lib/csapi/openid.h
+++ b/lib/csapi/openid.h
@@ -21,7 +21,7 @@ namespace Quotient {
* be used to request another OpenID access token or call `/sync`, for
* example.
*/
-class RequestOpenIdTokenJob : public BaseJob {
+class QUOTIENT_API RequestOpenIdTokenJob : public BaseJob {
public:
/*! \brief Get an OpenID token object to verify the requester's identity.
*
diff --git a/lib/csapi/peeking_events.h b/lib/csapi/peeking_events.h
index 885ff340..14cb6f0b 100644
--- a/lib/csapi/peeking_events.h
+++ b/lib/csapi/peeking_events.h
@@ -22,7 +22,7 @@ namespace Quotient {
* API will also be deprecated at some point, but its replacement is not
* yet known.
*/
-class PeekEventsJob : public BaseJob {
+class QUOTIENT_API PeekEventsJob : public BaseJob {
public:
/*! \brief Listen on the event stream.
*
diff --git a/lib/csapi/presence.h b/lib/csapi/presence.h
index 4ab50e25..52445205 100644
--- a/lib/csapi/presence.h
+++ b/lib/csapi/presence.h
@@ -15,7 +15,7 @@ namespace Quotient {
* not need to specify the `last_active_ago` field. You cannot set the
* presence state of another user.
*/
-class SetPresenceJob : public BaseJob {
+class QUOTIENT_API SetPresenceJob : public BaseJob {
public:
/*! \brief Update this user's presence state.
*
@@ -36,7 +36,7 @@ public:
*
* Get the given user's presence state.
*/
-class GetPresenceJob : public BaseJob {
+class QUOTIENT_API GetPresenceJob : public BaseJob {
public:
/*! \brief Get this user's presence state.
*
diff --git a/lib/csapi/profile.h b/lib/csapi/profile.h
index 7f9c9e95..b00c944b 100644
--- a/lib/csapi/profile.h
+++ b/lib/csapi/profile.h
@@ -13,7 +13,7 @@ namespace Quotient {
* This API sets the given user's display name. You must have permission to
* set this user's display name, e.g. you need to have their `access_token`.
*/
-class SetDisplayNameJob : public BaseJob {
+class QUOTIENT_API SetDisplayNameJob : public BaseJob {
public:
/*! \brief Set the user's display name.
*
@@ -33,7 +33,7 @@ public:
* own displayname or to query the name of other users; either locally or
* on remote homeservers.
*/
-class GetDisplayNameJob : public BaseJob {
+class QUOTIENT_API GetDisplayNameJob : public BaseJob {
public:
/*! \brief Get the user's display name.
*
@@ -63,7 +63,7 @@ public:
* This API sets the given user's avatar URL. You must have permission to
* set this user's avatar URL, e.g. you need to have their `access_token`.
*/
-class SetAvatarUrlJob : public BaseJob {
+class QUOTIENT_API SetAvatarUrlJob : public BaseJob {
public:
/*! \brief Set the user's avatar URL.
*
@@ -82,7 +82,7 @@ public:
* own avatar URL or to query the URL of other users; either locally or
* on remote homeservers.
*/
-class GetAvatarUrlJob : public BaseJob {
+class QUOTIENT_API GetAvatarUrlJob : public BaseJob {
public:
/*! \brief Get the user's avatar URL.
*
@@ -111,7 +111,7 @@ public:
* locally or on remote homeservers. This API may return keys which are not
* limited to `displayname` or `avatar_url`.
*/
-class GetUserProfileJob : public BaseJob {
+class QUOTIENT_API GetUserProfileJob : public BaseJob {
public:
/*! \brief Get this user's profile information.
*
diff --git a/lib/csapi/pusher.h b/lib/csapi/pusher.h
index 622b0df6..d859ffc4 100644
--- a/lib/csapi/pusher.h
+++ b/lib/csapi/pusher.h
@@ -12,7 +12,7 @@ namespace Quotient {
*
* Gets all currently active pushers for the authenticated user.
*/
-class GetPushersJob : public BaseJob {
+class QUOTIENT_API GetPushersJob : public BaseJob {
public:
// Inner data structures
@@ -108,7 +108,7 @@ struct JsonObjectConverter<GetPushersJob::Pusher> {
* [pushers](/client-server-api/#push-notifications) for this user ID. The
* behaviour of this endpoint varies depending on the values in the JSON body.
*/
-class PostPusherJob : public BaseJob {
+class QUOTIENT_API PostPusherJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/pushrules.h b/lib/csapi/pushrules.h
index a5eb48f0..d6c57efd 100644
--- a/lib/csapi/pushrules.h
+++ b/lib/csapi/pushrules.h
@@ -19,7 +19,7 @@ namespace Quotient {
* `/pushrules/global/`. This will return a subset of this data under the
* specified key e.g. the `global` key.
*/
-class GetPushRulesJob : public BaseJob {
+class QUOTIENT_API GetPushRulesJob : public BaseJob {
public:
/// Retrieve all push rulesets.
explicit GetPushRulesJob();
@@ -44,7 +44,7 @@ public:
*
* Retrieve a single specified push rule.
*/
-class GetPushRuleJob : public BaseJob {
+class QUOTIENT_API GetPushRuleJob : public BaseJob {
public:
/*! \brief Retrieve a push rule.
*
@@ -79,7 +79,7 @@ public:
*
* This endpoint removes the push rule defined in the path.
*/
-class DeletePushRuleJob : public BaseJob {
+class QUOTIENT_API DeletePushRuleJob : public BaseJob {
public:
/*! \brief Delete a push rule.
*
@@ -112,7 +112,7 @@ public:
*
* When creating push rules, they MUST be enabled by default.
*/
-class SetPushRuleJob : public BaseJob {
+class QUOTIENT_API SetPushRuleJob : public BaseJob {
public:
/*! \brief Add or change a push rule.
*
@@ -160,7 +160,7 @@ public:
*
* This endpoint gets whether the specified push rule is enabled.
*/
-class IsPushRuleEnabledJob : public BaseJob {
+class QUOTIENT_API IsPushRuleEnabledJob : public BaseJob {
public:
/*! \brief Get whether a push rule is enabled
*
@@ -195,7 +195,7 @@ public:
*
* This endpoint allows clients to enable or disable the specified push rule.
*/
-class SetPushRuleEnabledJob : public BaseJob {
+class QUOTIENT_API SetPushRuleEnabledJob : public BaseJob {
public:
/*! \brief Enable or disable a push rule.
*
@@ -219,7 +219,7 @@ public:
*
* This endpoint get the actions for the specified push rule.
*/
-class GetPushRuleActionsJob : public BaseJob {
+class QUOTIENT_API GetPushRuleActionsJob : public BaseJob {
public:
/*! \brief The actions for a push rule
*
@@ -258,7 +258,7 @@ public:
* This endpoint allows clients to change the actions of a push rule.
* This can be used to change the actions of builtin rules.
*/
-class SetPushRuleActionsJob : public BaseJob {
+class QUOTIENT_API SetPushRuleActionsJob : public BaseJob {
public:
/*! \brief Set the actions for a push rule.
*
diff --git a/lib/csapi/read_markers.h b/lib/csapi/read_markers.h
index 00a2aa0d..d13fa4fc 100644
--- a/lib/csapi/read_markers.h
+++ b/lib/csapi/read_markers.h
@@ -13,7 +13,7 @@ namespace Quotient {
* Sets the position of the read marker for a given room, and optionally
* the read receipt's location.
*/
-class SetReadMarkerJob : public BaseJob {
+class QUOTIENT_API SetReadMarkerJob : public BaseJob {
public:
/*! \brief Set the position of the read marker for a room.
*
diff --git a/lib/csapi/receipts.h b/lib/csapi/receipts.h
index 7ac093cd..e29e7b29 100644
--- a/lib/csapi/receipts.h
+++ b/lib/csapi/receipts.h
@@ -13,7 +13,7 @@ namespace Quotient {
* This API updates the marker for the given receipt type to the event ID
* specified.
*/
-class PostReceiptJob : public BaseJob {
+class QUOTIENT_API PostReceiptJob : public BaseJob {
public:
/*! \brief Send a receipt for the given event ID.
*
diff --git a/lib/csapi/redaction.h b/lib/csapi/redaction.h
index f0db9f9f..29d9c5d5 100644
--- a/lib/csapi/redaction.h
+++ b/lib/csapi/redaction.h
@@ -22,7 +22,7 @@ namespace Quotient {
*
* Server administrators may redact events sent by users on their server.
*/
-class RedactEventJob : public BaseJob {
+class QUOTIENT_API RedactEventJob : public BaseJob {
public:
/*! \brief Strips all non-integrity-critical information out of an event.
*
diff --git a/lib/csapi/registration.h b/lib/csapi/registration.h
index c1614f20..10375971 100644
--- a/lib/csapi/registration.h
+++ b/lib/csapi/registration.h
@@ -59,7 +59,7 @@ namespace Quotient {
* Any user ID returned by this API must conform to the grammar given in the
* [Matrix specification](/appendices/#user-identifiers).
*/
-class RegisterJob : public BaseJob {
+class QUOTIENT_API RegisterJob : public BaseJob {
public:
/*! \brief Register for an account on this homeserver.
*
@@ -143,7 +143,7 @@ public:
* should validate the email itself, either by sending a validation email
* itself or by using a service it has control over.
*/
-class RequestTokenToRegisterEmailJob : public BaseJob {
+class QUOTIENT_API RequestTokenToRegisterEmailJob : public BaseJob {
public:
/*! \brief Begins the validation process for an email to be used during
* registration.
@@ -175,7 +175,7 @@ public:
* should validate the phone number itself, either by sending a validation
* message itself or by using a service it has control over.
*/
-class RequestTokenToRegisterMSISDNJob : public BaseJob {
+class QUOTIENT_API RequestTokenToRegisterMSISDNJob : public BaseJob {
public:
/*! \brief Requests a validation token be sent to the given phone number for
* the purpose of registering an account
@@ -215,7 +215,7 @@ public:
* access token provided in the request. Whether other access tokens for
* the user are revoked depends on the request parameters.
*/
-class ChangePasswordJob : public BaseJob {
+class QUOTIENT_API ChangePasswordJob : public BaseJob {
public:
/*! \brief Changes a user's password.
*
@@ -257,7 +257,7 @@ public:
* The homeserver should validate the email itself, either by sending a
* validation email itself or by using a service it has control over.
*/
-class RequestTokenToResetPasswordEmailJob : public BaseJob {
+class QUOTIENT_API RequestTokenToResetPasswordEmailJob : public BaseJob {
public:
/*! \brief Requests a validation token be sent to the given email address
* for the purpose of resetting a user's password
@@ -309,7 +309,7 @@ public:
* The homeserver should validate the phone number itself, either by sending a
* validation message itself or by using a service it has control over.
*/
-class RequestTokenToResetPasswordMSISDNJob : public BaseJob {
+class QUOTIENT_API RequestTokenToResetPasswordMSISDNJob : public BaseJob {
public:
/*! \brief Requests a validation token be sent to the given phone number for
* the purpose of resetting a user's password.
@@ -361,7 +361,7 @@ public:
* parameter because the homeserver is expected to sign the request to the
* identity server instead.
*/
-class DeactivateAccountJob : public BaseJob {
+class QUOTIENT_API DeactivateAccountJob : public BaseJob {
public:
/*! \brief Deactivate a user's account.
*
@@ -411,7 +411,7 @@ public:
* reserve the username. This can mean that the username becomes unavailable
* between checking its availability and attempting to register it.
*/
-class CheckUsernameAvailabilityJob : public BaseJob {
+class QUOTIENT_API CheckUsernameAvailabilityJob : public BaseJob {
public:
/*! \brief Checks to see if a username is available on the server.
*
diff --git a/lib/csapi/report_content.h b/lib/csapi/report_content.h
index e401c2e1..8c533c19 100644
--- a/lib/csapi/report_content.h
+++ b/lib/csapi/report_content.h
@@ -13,7 +13,7 @@ namespace Quotient {
* Reports an event as inappropriate to the server, which may then notify
* the appropriate people.
*/
-class ReportContentJob : public BaseJob {
+class QUOTIENT_API ReportContentJob : public BaseJob {
public:
/*! \brief Reports an event as inappropriate.
*
diff --git a/lib/csapi/room_send.h b/lib/csapi/room_send.h
index 96f5beca..fea3d59d 100644
--- a/lib/csapi/room_send.h
+++ b/lib/csapi/room_send.h
@@ -18,7 +18,7 @@ namespace Quotient {
* fields in this object will vary depending on the type of event. See
* [Room Events](/client-server-api/#room-events) for the m. event specification.
*/
-class SendMessageJob : public BaseJob {
+class QUOTIENT_API SendMessageJob : public BaseJob {
public:
/*! \brief Send a message event to the given room.
*
diff --git a/lib/csapi/room_state.h b/lib/csapi/room_state.h
index f95af223..a00b0947 100644
--- a/lib/csapi/room_state.h
+++ b/lib/csapi/room_state.h
@@ -29,7 +29,7 @@ namespace Quotient {
* state event is to be sent. Servers do not validate aliases which are
* being removed or are already present in the state event.
*/
-class SetRoomStateWithKeyJob : public BaseJob {
+class QUOTIENT_API SetRoomStateWithKeyJob : public BaseJob {
public:
/*! \brief Send a state event to the given room.
*
diff --git a/lib/csapi/room_upgrades.h b/lib/csapi/room_upgrades.h
index 58327587..0432f667 100644
--- a/lib/csapi/room_upgrades.h
+++ b/lib/csapi/room_upgrades.h
@@ -12,7 +12,7 @@ namespace Quotient {
*
* Upgrades the given room to a particular room version.
*/
-class UpgradeRoomJob : public BaseJob {
+class QUOTIENT_API UpgradeRoomJob : public BaseJob {
public:
/*! \brief Upgrades a room to a new room version.
*
diff --git a/lib/csapi/rooms.h b/lib/csapi/rooms.h
index 2620582b..f0815109 100644
--- a/lib/csapi/rooms.h
+++ b/lib/csapi/rooms.h
@@ -15,7 +15,7 @@ namespace Quotient {
* Get a single event based on `roomId/eventId`. You must have permission to
* retrieve this event e.g. by being a member in the room for this event.
*/
-class GetOneRoomEventJob : public BaseJob {
+class QUOTIENT_API GetOneRoomEventJob : public BaseJob {
public:
/*! \brief Get a single event by event ID.
*
@@ -48,7 +48,7 @@ public:
* state of the room. If the user has left the room then the state is
* taken from the state of the room when they left.
*/
-class GetRoomStateWithKeyJob : public BaseJob {
+class QUOTIENT_API GetRoomStateWithKeyJob : public BaseJob {
public:
/*! \brief Get the state identified by the type and key.
*
@@ -80,7 +80,7 @@ public:
*
* Get the state events for the current state of a room.
*/
-class GetRoomStateJob : public BaseJob {
+class QUOTIENT_API GetRoomStateJob : public BaseJob {
public:
/*! \brief Get all state events in the current state of a room.
*
@@ -106,7 +106,7 @@ public:
*
* Get the list of members for this room.
*/
-class GetMembersByRoomJob : public BaseJob {
+class QUOTIENT_API GetMembersByRoomJob : public BaseJob {
public:
/*! \brief Get the m.room.member events for the room.
*
@@ -161,7 +161,7 @@ public:
* respond than `/members` as it can be implemented more efficiently on the
* server.
*/
-class GetJoinedMembersByRoomJob : public BaseJob {
+class QUOTIENT_API GetJoinedMembersByRoomJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/search.h b/lib/csapi/search.h
index 3d02752a..8683413d 100644
--- a/lib/csapi/search.h
+++ b/lib/csapi/search.h
@@ -15,7 +15,7 @@ namespace Quotient {
*
* Performs a full text search across different categories.
*/
-class SearchJob : public BaseJob {
+class QUOTIENT_API SearchJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/sso_login_redirect.h b/lib/csapi/sso_login_redirect.h
index ade1eb7d..f4f81c1e 100644
--- a/lib/csapi/sso_login_redirect.h
+++ b/lib/csapi/sso_login_redirect.h
@@ -17,7 +17,7 @@ namespace Quotient {
* or present a page which lets the user select an IdP to continue
* with in the event multiple are supported by the server.
*/
-class RedirectToSSOJob : public BaseJob {
+class QUOTIENT_API RedirectToSSOJob : public BaseJob {
public:
/*! \brief Redirect the user's browser to the SSO interface.
*
@@ -44,7 +44,7 @@ public:
* The server MUST respond with an HTTP redirect to the SSO interface
* for that IdP.
*/
-class RedirectToIdPJob : public BaseJob {
+class QUOTIENT_API RedirectToIdPJob : public BaseJob {
public:
/*! \brief Redirect the user's browser to the SSO interface for an IdP.
*
diff --git a/lib/csapi/tags.h b/lib/csapi/tags.h
index a854531a..f4250674 100644
--- a/lib/csapi/tags.h
+++ b/lib/csapi/tags.h
@@ -12,7 +12,7 @@ namespace Quotient {
*
* List the tags set by a user on a room.
*/
-class GetRoomTagsJob : public BaseJob {
+class QUOTIENT_API GetRoomTagsJob : public BaseJob {
public:
// Inner data structures
@@ -68,7 +68,7 @@ struct JsonObjectConverter<GetRoomTagsJob::Tag> {
*
* Add a tag to the room.
*/
-class SetRoomTagJob : public BaseJob {
+class QUOTIENT_API SetRoomTagJob : public BaseJob {
public:
/*! \brief Add a tag to a room.
*
@@ -98,7 +98,7 @@ public:
*
* Remove a tag from the room.
*/
-class DeleteRoomTagJob : public BaseJob {
+class QUOTIENT_API DeleteRoomTagJob : public BaseJob {
public:
/*! \brief Remove a tag from the room.
*
diff --git a/lib/csapi/third_party_lookup.h b/lib/csapi/third_party_lookup.h
index 969e767c..30c5346e 100644
--- a/lib/csapi/third_party_lookup.h
+++ b/lib/csapi/third_party_lookup.h
@@ -18,7 +18,7 @@ namespace Quotient {
* homeserver. Includes both the available protocols and all fields
* required for queries against each protocol.
*/
-class GetProtocolsJob : public BaseJob {
+class QUOTIENT_API GetProtocolsJob : public BaseJob {
public:
/// Retrieve metadata about all protocols that a homeserver supports.
explicit GetProtocolsJob();
@@ -45,7 +45,7 @@ public:
* Fetches the metadata from the homeserver about a particular third party
* protocol.
*/
-class GetProtocolMetadataJob : public BaseJob {
+class QUOTIENT_API GetProtocolMetadataJob : public BaseJob {
public:
/*! \brief Retrieve metadata about a specific protocol that the homeserver
* supports.
@@ -82,7 +82,7 @@ public:
* identifier. It should attempt to canonicalise the identifier as much
* as reasonably possible given the network type.
*/
-class QueryLocationByProtocolJob : public BaseJob {
+class QUOTIENT_API QueryLocationByProtocolJob : public BaseJob {
public:
/*! \brief Retrieve Matrix-side portals rooms leading to a third party
* location.
@@ -119,7 +119,7 @@ public:
* Retrieve a Matrix User ID linked to a user on the third party service, given
* a set of user parameters.
*/
-class QueryUserByProtocolJob : public BaseJob {
+class QUOTIENT_API QueryUserByProtocolJob : public BaseJob {
public:
/*! \brief Retrieve the Matrix User ID of a corresponding third party user.
*
@@ -155,7 +155,7 @@ public:
* Retrieve an array of third party network locations from a Matrix room
* alias.
*/
-class QueryLocationByAliasJob : public BaseJob {
+class QUOTIENT_API QueryLocationByAliasJob : public BaseJob {
public:
/*! \brief Reverse-lookup third party locations given a Matrix room alias.
*
@@ -184,7 +184,7 @@ public:
*
* Retrieve an array of third party users from a Matrix User ID.
*/
-class QueryUserByIDJob : public BaseJob {
+class QUOTIENT_API QueryUserByIDJob : public BaseJob {
public:
/*! \brief Reverse-lookup third party users given a Matrix User ID.
*
diff --git a/lib/csapi/third_party_membership.h b/lib/csapi/third_party_membership.h
index a424678f..1edb969e 100644
--- a/lib/csapi/third_party_membership.h
+++ b/lib/csapi/third_party_membership.h
@@ -52,7 +52,7 @@ namespace Quotient {
* If a token is requested from the identity server, the homeserver will
* append a `m.room.third_party_invite` event to the room.
*/
-class InviteBy3PIDJob : public BaseJob {
+class QUOTIENT_API InviteBy3PIDJob : public BaseJob {
public:
/*! \brief Invite a user to participate in a particular room.
*
diff --git a/lib/csapi/to_device.h b/lib/csapi/to_device.h
index 7a237195..5b6e0bfb 100644
--- a/lib/csapi/to_device.h
+++ b/lib/csapi/to_device.h
@@ -13,7 +13,7 @@ namespace Quotient {
* This endpoint is used to send send-to-device events to a set of
* client devices.
*/
-class SendToDeviceJob : public BaseJob {
+class QUOTIENT_API SendToDeviceJob : public BaseJob {
public:
/*! \brief Send an event to a given set of devices.
*
diff --git a/lib/csapi/typing.h b/lib/csapi/typing.h
index 64a310d0..234e91b0 100644
--- a/lib/csapi/typing.h
+++ b/lib/csapi/typing.h
@@ -15,7 +15,7 @@ namespace Quotient {
* Alternatively, if `typing` is `false`, it tells the server that the
* user has stopped typing.
*/
-class SetTypingJob : public BaseJob {
+class QUOTIENT_API SetTypingJob : public BaseJob {
public:
/*! \brief Informs the server that the user has started or stopped typing.
*
diff --git a/lib/csapi/users.h b/lib/csapi/users.h
index ec186592..3c99758b 100644
--- a/lib/csapi/users.h
+++ b/lib/csapi/users.h
@@ -21,7 +21,7 @@ namespace Quotient {
* names preferably using a collation determined based upon the
* `Accept-Language` header provided in the request, if present.
*/
-class SearchUserDirectoryJob : public BaseJob {
+class QUOTIENT_API SearchUserDirectoryJob : public BaseJob {
public:
// Inner data structures
diff --git a/lib/csapi/versions.h b/lib/csapi/versions.h
index 896e2ea9..4445dbd2 100644
--- a/lib/csapi/versions.h
+++ b/lib/csapi/versions.h
@@ -31,7 +31,7 @@ namespace Quotient {
* upgrade appropriately. Additionally, clients should avoid using unstable
* features in their stable releases.
*/
-class GetVersionsJob : public BaseJob {
+class QUOTIENT_API GetVersionsJob : public BaseJob {
public:
/// Gets the versions of the specification supported by the server.
explicit GetVersionsJob();
diff --git a/lib/csapi/voip.h b/lib/csapi/voip.h
index 087ebbbd..38904f60 100644
--- a/lib/csapi/voip.h
+++ b/lib/csapi/voip.h
@@ -13,7 +13,7 @@ namespace Quotient {
* This API provides credentials for the client to use when initiating
* calls.
*/
-class GetTurnServerJob : public BaseJob {
+class QUOTIENT_API GetTurnServerJob : public BaseJob {
public:
/// Obtain TURN server credentials.
explicit GetTurnServerJob();
diff --git a/lib/csapi/wellknown.h b/lib/csapi/wellknown.h
index c707d232..8615191c 100644
--- a/lib/csapi/wellknown.h
+++ b/lib/csapi/wellknown.h
@@ -21,7 +21,7 @@ namespace Quotient {
* Note that this endpoint is not necessarily handled by the homeserver,
* but by another webserver, to be used for discovering the homeserver URL.
*/
-class GetWellknownJob : public BaseJob {
+class QUOTIENT_API GetWellknownJob : public BaseJob {
public:
/// Gets Matrix server discovery information about the domain.
explicit GetWellknownJob();
diff --git a/lib/csapi/whoami.h b/lib/csapi/whoami.h
index 319f82c5..fba099f6 100644
--- a/lib/csapi/whoami.h
+++ b/lib/csapi/whoami.h
@@ -19,7 +19,7 @@ namespace Quotient {
* is registered by the appservice, and return it in the response
* body.
*/
-class GetTokenOwnerJob : public BaseJob {
+class QUOTIENT_API GetTokenOwnerJob : public BaseJob {
public:
/// Gets information about the owner of an access token.
explicit GetTokenOwnerJob();
diff --git a/lib/eventitem.cpp b/lib/eventitem.cpp
index 4f1595bc..a2d65d8d 100644
--- a/lib/eventitem.cpp
+++ b/lib/eventitem.cpp
@@ -25,3 +25,7 @@ void PendingEventItem::setFileUploaded(const QUrl& remoteUrl)
}
setStatus(EventStatus::FileUploaded);
}
+
+// Not exactly sure why but this helps with the linker not finding
+// Quotient::EventStatus::staticMetaObject when building Quaternion
+#include "moc_eventitem.cpp"
diff --git a/lib/eventitem.h b/lib/eventitem.h
index b411a90c..f04ef323 100644
--- a/lib/eventitem.h
+++ b/lib/eventitem.h
@@ -4,6 +4,7 @@
#pragma once
#include "events/stateevent.h"
+#include "quotient_common.h"
#include <any>
#include <utility>
@@ -11,7 +12,7 @@
namespace Quotient {
namespace EventStatus {
- Q_NAMESPACE
+ QUO_NAMESPACE
/** Special marks an event can assume
*
@@ -33,7 +34,7 @@ namespace EventStatus {
Q_ENUM_NS(Code)
} // namespace EventStatus
-class EventItemBase {
+class QUOTIENT_API EventItemBase {
public:
explicit EventItemBase(RoomEventPtr&& e) : evt(std::move(e))
{
@@ -74,7 +75,7 @@ private:
std::any data;
};
-class TimelineItem : public EventItemBase {
+class QUOTIENT_API TimelineItem : public EventItemBase {
public:
// For compatibility with Qt containers, even though we use
// a std:: container now for the room timeline
@@ -103,7 +104,7 @@ inline const CallEventBase* EventItemBase::viewAs<CallEventBase>() const
return evt->isCallEvent() ? weakPtrCast<const CallEventBase>(evt) : nullptr;
}
-class PendingEventItem : public EventItemBase {
+class QUOTIENT_API PendingEventItem : public EventItemBase {
public:
using EventItemBase::EventItemBase;
diff --git a/lib/events/accountdataevents.h b/lib/events/accountdataevents.h
index 9cf77be3..c0f2202d 100644
--- a/lib/events/accountdataevents.h
+++ b/lib/events/accountdataevents.h
@@ -50,7 +50,7 @@ struct JsonObjectConverter<TagRecord> {
using TagsMap = QHash<QString, TagRecord>;
#define DEFINE_SIMPLE_EVENT(_Name, _TypeId, _ContentType, _ContentKey) \
- class _Name : public Event { \
+ class QUOTIENT_API _Name : public Event { \
public: \
using content_type = _ContentType; \
DEFINE_EVENT_TYPEID(_TypeId, _Name) \
diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h
index 4c01c941..8ffe60f2 100644
--- a/lib/events/callanswerevent.h
+++ b/lib/events/callanswerevent.h
@@ -7,7 +7,7 @@
#include "roomevent.h"
namespace Quotient {
-class CallAnswerEvent : public CallEventBase {
+class QUOTIENT_API CallAnswerEvent : public CallEventBase {
public:
DEFINE_EVENT_TYPEID("m.call.answer", CallAnswerEvent)
@@ -26,6 +26,5 @@ public:
return contentPart<QJsonObject>("answer"_ls).value("sdp"_ls).toString();
}
};
-
REGISTER_EVENT_TYPE(CallAnswerEvent)
} // namespace Quotient
diff --git a/lib/events/callhangupevent.h b/lib/events/callhangupevent.h
index f3f82833..b0017c59 100644
--- a/lib/events/callhangupevent.h
+++ b/lib/events/callhangupevent.h
@@ -7,7 +7,7 @@
#include "roomevent.h"
namespace Quotient {
-class CallHangupEvent : public CallEventBase {
+class QUOTIENT_API CallHangupEvent : public CallEventBase {
public:
DEFINE_EVENT_TYPEID("m.call.hangup", CallHangupEvent)
diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h
index 80b7d651..47362b5c 100644
--- a/lib/events/callinviteevent.h
+++ b/lib/events/callinviteevent.h
@@ -7,7 +7,7 @@
#include "roomevent.h"
namespace Quotient {
-class CallInviteEvent : public CallEventBase {
+class QUOTIENT_API CallInviteEvent : public CallEventBase {
public:
DEFINE_EVENT_TYPEID("m.call.invite", CallInviteEvent)
diff --git a/lib/events/directchatevent.h b/lib/events/directchatevent.h
index e2143779..2018d3d6 100644
--- a/lib/events/directchatevent.h
+++ b/lib/events/directchatevent.h
@@ -6,7 +6,7 @@
#include "event.h"
namespace Quotient {
-class DirectChatEvent : public Event {
+class QUOTIENT_API DirectChatEvent : public Event {
public:
DEFINE_EVENT_TYPEID("m.direct", DirectChatEvent)
diff --git a/lib/events/encryptedevent.h b/lib/events/encryptedevent.h
index de89a7c6..81343a29 100644
--- a/lib/events/encryptedevent.h
+++ b/lib/events/encryptedevent.h
@@ -25,7 +25,7 @@ namespace Quotient {
* in general. It's possible, because RoomEvent interface is similar to Event's
* one and doesn't add new restrictions, just provides additional features.
*/
-class EncryptedEvent : public RoomEvent {
+class QUOTIENT_API EncryptedEvent : public RoomEvent {
public:
DEFINE_EVENT_TYPEID("m.room.encrypted", EncryptedEvent)
diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h
index 14439fcc..dfb28b2f 100644
--- a/lib/events/encryptionevent.h
+++ b/lib/events/encryptionevent.h
@@ -8,7 +8,7 @@
#include "stateevent.h"
namespace Quotient {
-class EncryptionEventContent : public EventContent::Base {
+class QUOTIENT_API EncryptionEventContent : public EventContent::Base {
public:
enum EncryptionType : size_t { MegolmV1AesSha2 = 0, Undefined };
@@ -26,7 +26,7 @@ protected:
using EncryptionType = EncryptionEventContent::EncryptionType;
-class EncryptionEvent : public StateEvent<EncryptionEventContent> {
+class QUOTIENT_API EncryptionEvent : public StateEvent<EncryptionEventContent> {
Q_GADGET
public:
DEFINE_EVENT_TYPEID("m.room.encryption", EncryptionEvent)
@@ -51,6 +51,5 @@ public:
int rotationPeriodMs() const { return content().rotationPeriodMs; }
int rotationPeriodMsgs() const { return content().rotationPeriodMsgs; }
};
-
REGISTER_EVENT_TYPE(EncryptionEvent)
} // namespace Quotient
diff --git a/lib/events/event.cpp b/lib/events/event.cpp
index 96be717c..4c304a3c 100644
--- a/lib/events/event.cpp
+++ b/lib/events/event.cpp
@@ -9,22 +9,14 @@
using namespace Quotient;
-event_type_t EventTypeRegistry::initializeTypeId(event_mtype_t matrixTypeId)
-{
- const auto id = get().eventTypes.size();
- get().eventTypes.push_back(matrixTypeId);
- if (strncmp(matrixTypeId, "", 1) == 0)
- qDebug(EVENTS) << "Initialized unknown event type with id" << id;
- else
- qDebug(EVENTS) << "Initialized event type" << matrixTypeId << "with id"
- << id;
- return id;
-}
+QString EventTypeRegistry::getMatrixType(event_type_t typeId) { return typeId; }
-QString EventTypeRegistry::getMatrixType(event_type_t typeId)
+void _impl::EventFactoryBase::logAddingMethod(event_type_t TypeId,
+ size_t newSize)
{
- return typeId < get().eventTypes.size() ? get().eventTypes[typeId]
- : QString();
+ qDebug(EVENTS) << "Adding factory method for" << TypeId << "events;"
+ << newSize << "methods will be in the" << name
+ << "chain";
}
Event::Event(Type type, const QJsonObject& json) : _type(type), _json(json)
diff --git a/lib/events/event.h b/lib/events/event.h
index 8347bb4f..f12e525e 100644
--- a/lib/events/event.h
+++ b/lib/events/event.h
@@ -55,60 +55,32 @@ inline QJsonObject basicEventJson(const QString& matrixType,
return { { TypeKey, matrixType }, { ContentKey, content } };
}
-// === Event types and event types registry ===
+// === Event types ===
-using event_type_t = size_t;
+using event_type_t = QLatin1String;
using event_mtype_t = const char*;
-class EventTypeRegistry {
+class QUOTIENT_API EventTypeRegistry {
public:
~EventTypeRegistry() = default;
- static event_type_t initializeTypeId(event_mtype_t matrixTypeId);
-
- template <typename EventT>
- static inline event_type_t initializeTypeId()
- {
- return initializeTypeId(EventT::matrixTypeId());
- }
-
+ [[deprecated("event_type_t is a string now, use it directly instead")]]
static QString getMatrixType(event_type_t typeId);
private:
EventTypeRegistry() = default;
Q_DISABLE_COPY_MOVE(EventTypeRegistry)
-
- static EventTypeRegistry& get()
- {
- static EventTypeRegistry etr;
- return etr;
- }
-
- std::vector<event_mtype_t> eventTypes;
-};
-
-template <>
-inline event_type_t EventTypeRegistry::initializeTypeId<void>()
-{
- return initializeTypeId("");
-}
-
-template <typename EventT>
-struct EventTypeTraits {
- static event_type_t id()
- {
- static const auto id = EventTypeRegistry::initializeTypeId<EventT>();
- return id;
- }
};
template <typename EventT>
-inline event_type_t typeId()
+constexpr event_type_t typeId()
{
- return EventTypeTraits<std::decay_t<EventT>>::id();
+ return std::decay_t<EventT>::TypeId;
}
-inline event_type_t unknownEventTypeId() { return typeId<void>(); }
+constexpr event_type_t UnknownEventTypeId = "?"_ls;
+[[deprecated("Use UnknownEventTypeId")]]
+constexpr event_type_t unknownEventTypeId() { return UnknownEventTypeId; }
// === Event creation facilities ===
@@ -120,80 +92,98 @@ inline event_ptr_tt<EventT> makeEvent(ArgTs&&... args)
}
namespace _impl {
- template <class EventT, class BaseEventT>
- event_ptr_tt<BaseEventT> makeIfMatches(const QJsonObject& json,
- const QString& matrixType)
- {
- return QLatin1String(EventT::matrixTypeId()) == matrixType
- ? makeEvent<EventT>(json)
- : nullptr;
- }
-
- //! \brief A family of event factories to create events from CS API responses
- //!
- //! Each of these factories, as instantiated by event base types (Event,
- //! RoomEvent etc.) is capable of producing an event object derived from
- //! \p BaseEventT, using the JSON payload and the event type passed to its
- //! make() method. Don't use these directly to make events; use loadEvent()
- //! overloads as the frontend for these. Never instantiate new factories
- //! outside of base event classes.
- //! \sa loadEvent, setupFactory, Event::factory, RoomEvent::factory,
- //! StateEventBase::factory
- template <typename BaseEventT>
- class EventFactory
- : private std::vector<event_ptr_tt<BaseEventT> (*)(const QJsonObject&,
- const QString&)> {
- // Actual makeIfMatches specialisations will differ in the first
- // template parameter but that doesn't affect the function type
+ class QUOTIENT_API EventFactoryBase {
public:
- explicit EventFactory(const char* name)
+ EventFactoryBase(const EventFactoryBase&) = delete;
+
+ protected: // This class is only to inherit from
+ explicit EventFactoryBase(const char* name)
: name(name)
- {
- static auto yetToBeConstructed = true;
- Q_ASSERT(yetToBeConstructed);
- if (!yetToBeConstructed) // For Release builds that pass Q_ASSERT
- qCritical(EVENTS)
- << "Another EventFactory for the same base type is being "
- "created - event creation logic will be splintered";
- yetToBeConstructed = false;
- }
- EventFactory(const EventFactory&) = delete;
-
- //! \brief Add a method to create events of a given type
- //!
- //! Adds a standard factory method (makeIfMatches) for \p EventT so that
- //! event objects of this type can be created dynamically by loadEvent.
- //! The caller is responsible for ensuring this method is called only
- //! once per type.
- //! \sa makeIfMatches, loadEvent, Quotient::loadEvent
- template <class EventT>
- bool addMethod()
- {
- this->emplace_back(&makeIfMatches<EventT, BaseEventT>);
- qDebug(EVENTS) << "Added factory method for"
- << EventT::matrixTypeId() << "events;" << this->size()
- << "methods in the" << name << "chain by now";
- return true;
- }
-
- auto loadEvent(const QJsonObject& json, const QString& matrixType)
- {
- for (const auto& f : *this)
- if (auto e = f(json, matrixType))
- return e;
- return makeEvent<BaseEventT>(unknownEventTypeId(), json);
- }
+ {}
+ void logAddingMethod(event_type_t TypeId, size_t newSize);
+ private:
const char* const name;
};
} // namespace _impl
+//! \brief A family of event factories to create events from CS API responses
+//!
+//! Each of these factories, as instantiated by event base types (Event,
+//! RoomEvent etc.) is capable of producing an event object derived from
+//! \p BaseEventT, using the JSON payload and the event type passed to its
+//! make() method. Don't use these directly to make events; use loadEvent()
+//! overloads as the frontend for these. Never instantiate new factories
+//! outside of base event classes.
+//! \sa loadEvent, setupFactory, Event::factory, RoomEvent::factory,
+//! StateEventBase::factory
+template <typename BaseEventT>
+class EventFactory : public _impl::EventFactoryBase {
+private:
+ using method_t = event_ptr_tt<BaseEventT> (*)(const QJsonObject&,
+ const QString&);
+ std::vector<method_t> methods {};
+
+ template <class EventT>
+ static event_ptr_tt<BaseEventT> makeIfMatches(const QJsonObject& json,
+ const QString& matrixType)
+ {
+ // If your matrix event type is not all ASCII, it's your problem
+ // (see https://github.com/matrix-org/matrix-doc/pull/2758)
+ return EventT::TypeId == matrixType ? makeEvent<EventT>(json) : nullptr;
+ }
+
+public:
+ explicit EventFactory(const char* fName)
+ : EventFactoryBase { fName }
+ {}
+
+ //! \brief Add a method to create events of a given type
+ //!
+ //! Adds a standard factory method (makeIfMatches) for \p EventT so that
+ //! event objects of this type can be created dynamically by loadEvent.
+ //! The caller is responsible for ensuring this method is called only
+ //! once per type.
+ //! \sa loadEvent, Quotient::loadEvent
+ template <class EventT>
+ const auto& addMethod()
+ {
+ const auto m = &makeIfMatches<EventT>;
+ const auto it = std::find(methods.cbegin(), methods.cend(), m);
+ if (it != methods.cend())
+ return *it;
+ logAddingMethod(EventT::TypeId, methods.size() + 1);
+ return methods.emplace_back(m);
+ }
+
+ auto loadEvent(const QJsonObject& json, const QString& matrixType)
+ {
+ for (const auto& f : methods)
+ if (auto e = f(json, matrixType))
+ return e;
+ return makeEvent<BaseEventT>(UnknownEventTypeId, json);
+ }
+};
+
+//! \brief Point of customisation to dynamically load events
+//!
+//! The default specialisation of this calls BaseEventT::factory.loadEvent()
+//! and if that fails (i.e. returns nullptr) creates an unknown event of
+//! BaseEventT. Other specialisations may reuse other factories, add validations
+//! common to BaseEventT events, and so on.
+template <class BaseEventT>
+event_ptr_tt<BaseEventT> doLoadEvent(const QJsonObject& json,
+ const QString& matrixType)
+{
+ return BaseEventT::factory.loadEvent(json, matrixType);
+}
+
// === Event ===
-class Event {
+class QUOTIENT_API Event {
public:
using Type = event_type_t;
- static inline _impl::EventFactory<Event> factory { "Event" };
+ static inline EventFactory<Event> factory { "Event" };
explicit Event(Type type, const QJsonObject& json);
explicit Event(Type type, event_mtype_t matrixType,
@@ -243,7 +233,7 @@ public:
return fromJson<T>(unsignedJson()[std::forward<KeyT>(key)]);
}
- friend QDebug operator<<(QDebug dbg, const Event& e)
+ friend QUOTIENT_API QDebug operator<<(QDebug dbg, const Event& e)
{
QDebugStateSaver _dss { dbg };
dbg.noquote().nospace() << e.matrixType() << '(' << e.type() << "): ";
@@ -272,35 +262,22 @@ using Events = EventsArray<Event>;
// This macro should be used in a public section of an event class to
// provide matrixTypeId() and typeId().
-#define DEFINE_EVENT_TYPEID(_Id, _Type) \
- static constexpr event_mtype_t matrixTypeId() { return _Id; } \
- static auto typeId() { return Quotient::typeId<_Type>(); } \
+#define DEFINE_EVENT_TYPEID(Id_, Type_) \
+ static constexpr event_type_t TypeId = Id_##_ls; \
+ [[deprecated("Use _Type::TypeId directly instead")]] \
+ static constexpr event_mtype_t matrixTypeId() { return Id_; } \
+ [[deprecated("Use _Type::TypeId directly instead")]] \
+ static event_type_t typeId() { return TypeId; } \
// End of macro
// This macro should be put after an event class definition (in .h or .cpp)
// to enable its deserialisation from a /sync and other
// polymorphic event arrays
-#define REGISTER_EVENT_TYPE(_Type) \
- [[maybe_unused]] inline const auto _factoryAdded##_Type = \
- _Type::factory.addMethod<_Type>(); \
+#define REGISTER_EVENT_TYPE(Type_) \
+ [[maybe_unused]] inline const auto& factoryMethodFor##Type_ = \
+ Type_::factory.addMethod<Type_>(); \
// End of macro
-// === Event loading ===
-// (see also event_loader.h)
-
-//! \brief Point of customisation to dynamically load events
-//!
-//! The default specialisation of this calls BaseEventT::factory and if that
-//! fails (i.e. returns nullptr) creates an unknown event of BaseEventT.
-//! Other specialisations may reuse other factories, add validations common to
-//! BaseEventT, and so on
-template <class BaseEventT>
-event_ptr_tt<BaseEventT> doLoadEvent(const QJsonObject& json,
- const QString& matrixType)
-{
- return BaseEventT::factory.loadEvent(json, matrixType);
-}
-
// === is<>(), eventCast<>() and switchOnType<>() ===
template <class EventT>
@@ -311,7 +288,7 @@ inline bool is(const Event& e)
inline bool isUnknown(const Event& e)
{
- return e.type() == unknownEventTypeId();
+ return e.type() == UnknownEventTypeId;
}
template <class EventT, typename BasePtrT>
diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h
index f6dbd4bf..87ea3672 100644
--- a/lib/events/eventcontent.h
+++ b/lib/events/eventcontent.h
@@ -6,14 +6,15 @@
// This file contains generic event content definitions, applicable to room
// message events as well as other events (e.g., avatars).
+#include "encryptedfile.h"
+#include "quotient_export.h"
+
#include <QtCore/QJsonObject>
#include <QtCore/QMimeType>
#include <QtCore/QSize>
#include <QtCore/QUrl>
#include <QtCore/QMetaType>
-#include "encryptedfile.h"
-
class QFileInfo;
namespace Quotient {
@@ -28,7 +29,7 @@ namespace EventContent {
* assumed but not required that a content object can also be created
* from plain data.
*/
- class Base {
+ class QUOTIENT_API Base {
public:
explicit Base(QJsonObject o = {}) : originalJson(std::move(o)) {}
virtual ~Base() = default;
@@ -76,7 +77,7 @@ namespace EventContent {
*
* This class is not polymorphic.
*/
- class FileInfo {
+ class QUOTIENT_API FileInfo {
public:
FileInfo() = default;
explicit FileInfo(const QFileInfo& fi);
@@ -121,7 +122,7 @@ namespace EventContent {
/**
* A content info class for image content types: image, thumbnail, video
*/
- class ImageInfo : public FileInfo {
+ class QUOTIENT_API ImageInfo : public FileInfo {
public:
ImageInfo() = default;
explicit ImageInfo(const QFileInfo& fi, QSize imageSize = {});
@@ -146,7 +147,7 @@ namespace EventContent {
* the JSON representation of event content; namely,
* "info/thumbnail_url" and "info/thumbnail_info" fields are used.
*/
- class Thumbnail : public ImageInfo {
+ class QUOTIENT_API Thumbnail : public ImageInfo {
public:
Thumbnail() = default; // Allow empty thumbnails
Thumbnail(const QJsonObject& infoJson, const Omittable<EncryptedFile> &file = none);
@@ -160,7 +161,7 @@ namespace EventContent {
void fillInfoJson(QJsonObject* infoJson) const;
};
- class TypedBase : public Base {
+ class QUOTIENT_API TypedBase : public Base {
public:
virtual QMimeType type() const = 0;
virtual const FileInfo* fileInfo() const { return nullptr; }
@@ -183,7 +184,7 @@ namespace EventContent {
* \tparam InfoT base info class
*/
template <class InfoT>
- class UrlBasedContent : public TypedBase, public InfoT {
+ class QUOTIENT_API UrlBasedContent : public TypedBase, public InfoT {
public:
using InfoT::InfoT;
explicit UrlBasedContent(const QJsonObject& json)
@@ -215,7 +216,7 @@ namespace EventContent {
};
template <typename InfoT>
- class UrlWithThumbnailContent : public UrlBasedContent<InfoT> {
+ class QUOTIENT_API UrlWithThumbnailContent : public UrlBasedContent<InfoT> {
public:
// NB: when using inherited constructors, thumbnail has to be
// initialised separately
diff --git a/lib/events/reactionevent.h b/lib/events/reactionevent.h
index 5a2b98c4..ce11eaed 100644
--- a/lib/events/reactionevent.h
+++ b/lib/events/reactionevent.h
@@ -7,7 +7,7 @@
namespace Quotient {
-struct EventRelation {
+struct QUOTIENT_API EventRelation {
using reltypeid_t = const char*;
static constexpr reltypeid_t Reply() { return "m.in_reply_to"; }
static constexpr reltypeid_t Annotation() { return "m.annotation"; }
@@ -31,12 +31,12 @@ struct EventRelation {
}
};
template <>
-struct JsonObjectConverter<EventRelation> {
+struct QUOTIENT_API JsonObjectConverter<EventRelation> {
static void dumpTo(QJsonObject& jo, const EventRelation& pod);
static void fillFrom(const QJsonObject& jo, EventRelation& pod);
};
-class ReactionEvent : public RoomEvent {
+class QUOTIENT_API ReactionEvent : public RoomEvent {
public:
DEFINE_EVENT_TYPEID("m.reaction", ReactionEvent)
diff --git a/lib/events/receiptevent.h b/lib/events/receiptevent.h
index 9683deef..5e077e47 100644
--- a/lib/events/receiptevent.h
+++ b/lib/events/receiptevent.h
@@ -19,7 +19,7 @@ struct ReceiptsForEvent {
};
using EventsWithReceipts = QVector<ReceiptsForEvent>;
-class ReceiptEvent : public Event {
+class QUOTIENT_API ReceiptEvent : public Event {
public:
DEFINE_EVENT_TYPEID("m.receipt", ReceiptEvent)
explicit ReceiptEvent(const EventsWithReceipts& ewrs);
diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h
index 8618ba31..c54b5801 100644
--- a/lib/events/roomavatarevent.h
+++ b/lib/events/roomavatarevent.h
@@ -7,7 +7,8 @@
#include "stateevent.h"
namespace Quotient {
-class RoomAvatarEvent : public StateEvent<EventContent::ImageContent> {
+class QUOTIENT_API RoomAvatarEvent
+ : public StateEvent<EventContent::ImageContent> {
// It's a bit of an overkill to use a full-fledged ImageContent
// because in reality m.room.avatar usually only has a single URL,
// without a thumbnail. But The Spec says there be thumbnails, and
diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h
index b3ad287c..016855b9 100644
--- a/lib/events/roomcreateevent.h
+++ b/lib/events/roomcreateevent.h
@@ -7,7 +7,7 @@
#include "quotient_common.h"
namespace Quotient {
-class RoomCreateEvent : public StateEventBase {
+class QUOTIENT_API RoomCreateEvent : public StateEventBase {
public:
DEFINE_EVENT_TYPEID("m.room.create", RoomCreateEvent)
diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h
index 8be58481..dcee1170 100644
--- a/lib/events/roomevent.h
+++ b/lib/events/roomevent.h
@@ -11,9 +11,9 @@ namespace Quotient {
class RedactionEvent;
/** This class corresponds to m.room.* events */
-class RoomEvent : public Event {
+class QUOTIENT_API RoomEvent : public Event {
public:
- static inline _impl::EventFactory<RoomEvent> factory { "RoomEvent" };
+ static inline EventFactory<RoomEvent> factory { "RoomEvent" };
// RedactionEvent is an incomplete type here so we cannot inline
// constructors and destructors and we cannot use 'using'.
@@ -70,7 +70,7 @@ using RoomEventPtr = event_ptr_tt<RoomEvent>;
using RoomEvents = EventsArray<RoomEvent>;
using RoomEventsRange = Range<RoomEvents>;
-class CallEventBase : public RoomEvent {
+class QUOTIENT_API CallEventBase : public RoomEvent {
public:
CallEventBase(Type type, event_mtype_t matrixType, const QString& callId,
int version, const QJsonObject& contentJson = {});
diff --git a/lib/events/roomkeyevent.h b/lib/events/roomkeyevent.h
index d021fbec..c4df7936 100644
--- a/lib/events/roomkeyevent.h
+++ b/lib/events/roomkeyevent.h
@@ -6,7 +6,7 @@
#include "event.h"
namespace Quotient {
-class RoomKeyEvent : public Event
+class QUOTIENT_API RoomKeyEvent : public Event
{
public:
DEFINE_EVENT_TYPEID("m.room_key", RoomKeyEvent)
diff --git a/lib/events/roommemberevent.h b/lib/events/roommemberevent.h
index 0fb464d4..5e446dbe 100644
--- a/lib/events/roommemberevent.h
+++ b/lib/events/roommemberevent.h
@@ -10,7 +10,7 @@
#include "quotient_common.h"
namespace Quotient {
-class MemberEventContent : public EventContent::Base {
+class QUOTIENT_API MemberEventContent : public EventContent::Base {
public:
using MembershipType
[[deprecated("Use Quotient::Membership instead")]] = Membership;
@@ -33,7 +33,7 @@ protected:
using MembershipType [[deprecated("Use Membership instead")]] = Membership;
-class RoomMemberEvent : public StateEvent<MemberEventContent> {
+class QUOTIENT_API RoomMemberEvent : public StateEvent<MemberEventContent> {
Q_GADGET
public:
DEFINE_EVENT_TYPEID("m.room.member", RoomMemberEvent)
@@ -95,6 +95,5 @@ doLoadEvent<RoomMemberEvent>(const QJsonObject& json, const QString& matrixType)
return makeEvent<RoomMemberEvent>(json);
return makeEvent<RoomMemberEvent>(unknownEventTypeId(), json);
}
-
REGISTER_EVENT_TYPE(RoomMemberEvent)
} // namespace Quotient
diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h
index 56597ddc..0c901b7a 100644
--- a/lib/events/roommessageevent.h
+++ b/lib/events/roommessageevent.h
@@ -16,7 +16,7 @@ namespace MessageEventContent = EventContent; // Back-compatibility
/**
* The event class corresponding to m.room.message events
*/
-class RoomMessageEvent : public RoomEvent {
+class QUOTIENT_API RoomMessageEvent : public RoomEvent {
Q_GADGET
public:
DEFINE_EVENT_TYPEID("m.room.message", RoomMessageEvent)
@@ -120,7 +120,7 @@ namespace EventContent {
* Available fields: mimeType, body. The body can be either rich text
* or plain text, depending on what mimeType specifies.
*/
- class TextContent : public TypedBase {
+ class QUOTIENT_API TextContent : public TypedBase {
public:
TextContent(QString text, const QString& contentType,
Omittable<RelatesTo> relatesTo = none);
@@ -149,7 +149,7 @@ namespace EventContent {
* - thumbnail.mimeType
* - thumbnail.imageSize
*/
- class LocationContent : public TypedBase {
+ class QUOTIENT_API LocationContent : public TypedBase {
public:
LocationContent(const QString& geoUri, const Thumbnail& thumbnail = {});
explicit LocationContent(const QJsonObject& json);
@@ -168,7 +168,7 @@ namespace EventContent {
* A base class for info types that include duration: audio and video
*/
template <typename ContentT>
- class PlayableContent : public ContentT {
+ class QUOTIENT_API PlayableContent : public ContentT {
public:
using ContentT::ContentT;
PlayableContent(const QJsonObject& json)
diff --git a/lib/events/roompowerlevelsevent.h b/lib/events/roompowerlevelsevent.h
index 0346fc0d..80e27048 100644
--- a/lib/events/roompowerlevelsevent.h
+++ b/lib/events/roompowerlevelsevent.h
@@ -7,7 +7,7 @@
#include "stateevent.h"
namespace Quotient {
-class PowerLevelsEventContent : public EventContent::Base {
+class QUOTIENT_API PowerLevelsEventContent : public EventContent::Base {
public:
struct Notifications {
int room;
@@ -34,7 +34,8 @@ protected:
void fillJson(QJsonObject* o) const override;
};
-class RoomPowerLevelsEvent : public StateEvent<PowerLevelsEventContent> {
+class QUOTIENT_API RoomPowerLevelsEvent
+ : public StateEvent<PowerLevelsEventContent> {
Q_GADGET
public:
DEFINE_EVENT_TYPEID("m.room.power_levels", RoomPowerLevelsEvent)
@@ -61,9 +62,6 @@ public:
int powerLevelForEvent(const QString& eventId) const;
int powerLevelForState(const QString& eventId) const;
int powerLevelForUser(const QString& userId) const;
-
-private:
};
-
REGISTER_EVENT_TYPE(RoomPowerLevelsEvent)
} // namespace Quotient
diff --git a/lib/events/roomtombstoneevent.h b/lib/events/roomtombstoneevent.h
index 30e53738..e336c448 100644
--- a/lib/events/roomtombstoneevent.h
+++ b/lib/events/roomtombstoneevent.h
@@ -6,7 +6,7 @@
#include "stateevent.h"
namespace Quotient {
-class RoomTombstoneEvent : public StateEventBase {
+class QUOTIENT_API RoomTombstoneEvent : public StateEventBase {
public:
DEFINE_EVENT_TYPEID("m.room.tombstone", RoomTombstoneEvent)
diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h
index 13597979..e6c05880 100644
--- a/lib/events/simplestateevents.h
+++ b/lib/events/simplestateevents.h
@@ -30,7 +30,8 @@ namespace EventContent {
} // namespace EventContent
#define DEFINE_SIMPLE_STATE_EVENT(_Name, _TypeId, _ValueType, _ContentKey) \
- class _Name : public StateEvent<EventContent::SimpleContent<_ValueType>> { \
+ class QUOTIENT_API _Name \
+ : public StateEvent<EventContent::SimpleContent<_ValueType>> { \
public: \
using value_type = content_type::value_type; \
DEFINE_EVENT_TYPEID(_TypeId, _Name) \
diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h
index c37965aa..88da68f8 100644
--- a/lib/events/stateevent.h
+++ b/lib/events/stateevent.h
@@ -17,9 +17,9 @@ inline QJsonObject basicStateEventJson(const QString& matrixTypeId,
{ ContentKey, content } };
}
-class StateEventBase : public RoomEvent {
+class QUOTIENT_API StateEventBase : public RoomEvent {
public:
- static inline _impl::EventFactory<StateEventBase> factory { "StateEvent" };
+ static inline EventFactory<StateEventBase> factory { "StateEvent" };
StateEventBase(Type type, const QJsonObject& json);
StateEventBase(Type type, event_mtype_t matrixType,
diff --git a/lib/events/stickerevent.h b/lib/events/stickerevent.h
index 93671086..0957dca3 100644
--- a/lib/events/stickerevent.h
+++ b/lib/events/stickerevent.h
@@ -11,7 +11,7 @@ namespace Quotient {
/// Sticker messages are specialised image messages that are displayed without
/// controls (e.g. no "download" link, or light-box view on click, as would be
/// displayed for for m.image events).
-class StickerEvent : public RoomEvent
+class QUOTIENT_API StickerEvent : public RoomEvent
{
public:
DEFINE_EVENT_TYPEID("m.sticker", StickerEvent)
diff --git a/lib/events/typingevent.h b/lib/events/typingevent.h
index 7456100a..522f7e42 100644
--- a/lib/events/typingevent.h
+++ b/lib/events/typingevent.h
@@ -6,7 +6,7 @@
#include "event.h"
namespace Quotient {
-class TypingEvent : public Event {
+class QUOTIENT_API TypingEvent : public Event {
public:
DEFINE_EVENT_TYPEID("m.typing", TypingEvent)
diff --git a/lib/eventstats.h b/lib/eventstats.h
index 77c661a7..a10c81fb 100644
--- a/lib/eventstats.h
+++ b/lib/eventstats.h
@@ -16,7 +16,7 @@ namespace Quotient {
//! \note It's just a simple grouping of counters and is not automatically
//! updated from the room as subsequent syncs arrive.
//! \sa Room::unreadStats, Room::partiallyReadStats, Room::isEventNotable
-struct EventStats {
+struct QUOTIENT_API EventStats {
Q_GADGET
Q_PROPERTY(qsizetype notableCount MEMBER notableCount CONSTANT)
Q_PROPERTY(qsizetype highlightCount MEMBER highlightCount CONSTANT)
@@ -109,6 +109,6 @@ public:
bool isValidFor(const Room* room, const marker_t& marker) const;
};
-QDebug operator<<(QDebug dbg, const EventStats& es);
+QUOTIENT_API QDebug operator<<(QDebug dbg, const EventStats& es);
}
diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h
index ddf243ed..f41fc63c 100644
--- a/lib/jobs/basejob.h
+++ b/lib/jobs/basejob.h
@@ -20,7 +20,7 @@ class ConnectionData;
enum class HttpVerb { Get, Put, Post, Delete };
-class BaseJob : public QObject {
+class QUOTIENT_API BaseJob : public QObject {
Q_OBJECT
Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT)
Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries)
@@ -470,7 +470,7 @@ private:
QScopedPointer<Private> d;
};
-inline bool isJobPending(BaseJob* job)
+inline bool QUOTIENT_API isJobPending(BaseJob* job)
{
return job && job->error() == BaseJob::Pending;
}
diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp
index 0b0531ad..6bf221cb 100644
--- a/lib/jobs/downloadfilejob.cpp
+++ b/lib/jobs/downloadfilejob.cpp
@@ -37,6 +37,8 @@ DownloadFileJob::DownloadFileJob(const QString& serverName,
setObjectName(QStringLiteral("DownloadFileJob"));
}
+DownloadFileJob::~DownloadFileJob() = default;
+
QString DownloadFileJob::targetFileName() const
{
return (d->targetFile ? d->targetFile : d->tempFile)->fileName();
diff --git a/lib/jobs/downloadfilejob.h b/lib/jobs/downloadfilejob.h
index 0752af89..9e807fe7 100644
--- a/lib/jobs/downloadfilejob.h
+++ b/lib/jobs/downloadfilejob.h
@@ -6,13 +6,14 @@
#include "csapi/content-repo.h"
namespace Quotient {
-class DownloadFileJob : public GetContentJob {
+class QUOTIENT_API DownloadFileJob : public GetContentJob {
public:
using GetContentJob::makeRequestUrl;
static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri);
DownloadFileJob(const QString& serverName, const QString& mediaId,
const QString& localFilename = {});
+ ~DownloadFileJob() override;
QString targetFileName() const;
diff --git a/lib/jobs/mediathumbnailjob.h b/lib/jobs/mediathumbnailjob.h
index 3183feb1..c9f6da35 100644
--- a/lib/jobs/mediathumbnailjob.h
+++ b/lib/jobs/mediathumbnailjob.h
@@ -8,7 +8,7 @@
#include <QtGui/QPixmap>
namespace Quotient {
-class MediaThumbnailJob : public GetContentThumbnailJob {
+class QUOTIENT_API MediaThumbnailJob : public GetContentThumbnailJob {
public:
using GetContentThumbnailJob::makeRequestUrl;
static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri,
diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h
index 4f05e5ff..41ad833a 100644
--- a/lib/jobs/requestdata.h
+++ b/lib/jobs/requestdata.h
@@ -3,6 +3,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtCore/QByteArray>
#include <memory>
@@ -19,7 +21,7 @@ namespace Quotient {
* as well as JSON (and possibly other structures in the future) to
* a QByteArray consumed by QNetworkAccessManager request methods.
*/
-class RequestData {
+class QUOTIENT_API RequestData {
public:
RequestData(const QByteArray& a = {});
RequestData(const QJsonObject& jo);
diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp
index 0b6643fc..fb16c79f 100644
--- a/lib/mxcreply.cpp
+++ b/lib/mxcreply.cpp
@@ -38,6 +38,8 @@ MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId)
});
}
+MxcReply::~MxcReply() = default;
+
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#define ERROR_SIGNAL errorOccurred
#else
diff --git a/lib/mxcreply.h b/lib/mxcreply.h
index efaf01c6..1d31d608 100644
--- a/lib/mxcreply.h
+++ b/lib/mxcreply.h
@@ -3,18 +3,22 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtNetwork/QNetworkReply>
#include <memory>
namespace Quotient {
class Room;
-class MxcReply : public QNetworkReply
+class QUOTIENT_API MxcReply : public QNetworkReply
{
+ Q_OBJECT
public:
explicit MxcReply();
explicit MxcReply(QNetworkReply *reply);
MxcReply(QNetworkReply* reply, Room* room, const QString& eventId);
+ ~MxcReply() override;
public Q_SLOTS:
void abort() override;
diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h
index 87bc12a1..d06f9736 100644
--- a/lib/networkaccessmanager.h
+++ b/lib/networkaccessmanager.h
@@ -3,6 +3,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtNetwork/QNetworkAccessManager>
#include <memory>
@@ -10,7 +12,7 @@
namespace Quotient {
class Room;
class Connection;
-class NetworkAccessManager : public QNetworkAccessManager {
+class QUOTIENT_API NetworkAccessManager : public QNetworkAccessManager {
Q_OBJECT
public:
NetworkAccessManager(QObject* parent = nullptr);
diff --git a/lib/networksettings.h b/lib/networksettings.h
index b83a0e15..44247e59 100644
--- a/lib/networksettings.h
+++ b/lib/networksettings.h
@@ -10,7 +10,7 @@
Q_DECLARE_METATYPE(QNetworkProxy::ProxyType)
namespace Quotient {
-class NetworkSettings : public SettingsGroup {
+class QUOTIENT_API NetworkSettings : public SettingsGroup {
Q_OBJECT
QUO_DECLARE_SETTING(QNetworkProxy::ProxyType, proxyType, setProxyType)
QUO_DECLARE_SETTING(QString, proxyHostName, setProxyHostName)
diff --git a/lib/quotient_common.h b/lib/quotient_common.h
index 0e3e2a40..3d38ce1f 100644
--- a/lib/quotient_common.h
+++ b/lib/quotient_common.h
@@ -3,6 +3,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <qobjectdefs.h>
#include <array>
@@ -26,8 +28,21 @@
#define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended) \
Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended
+#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
+// The first line forward-declares the namespace static metaobject with
+// QUOTIENT_API so that dynamically linked clients could serialise flag/enum
+// values from the namespace; Qt before 5.14 doesn't help with that. The second
+// line is needed for moc to do its job on the namespace.
+#define QUO_NAMESPACE \
+ extern QUOTIENT_API const QMetaObject staticMetaObject; \
+ Q_NAMESPACE
+#else
+// Since Qt 5.14.0, it's all packed in a single macro
+#define QUO_NAMESPACE Q_NAMESPACE_EXPORT(QUOTIENT_API)
+#endif
+
namespace Quotient {
-Q_NAMESPACE
+QUO_NAMESPACE
// std::array {} needs explicit template parameters on macOS because
// Apple stdlib doesn't have deduction guides for std::array. C++20 has
diff --git a/lib/quotient_export.h b/lib/quotient_export.h
new file mode 100644
index 00000000..5a6edb0e
--- /dev/null
+++ b/lib/quotient_export.h
@@ -0,0 +1,23 @@
+// SPDX-FileCopyrightText: 2021 Kitsune Ral <kitsune-ral@users.sf.net>
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#pragma once
+
+#ifdef QUOTIENT_STATIC
+# define QUOTIENT_API
+# define QUOTIENT_HIDDEN
+#else
+# ifndef QUOTIENT_API
+# ifdef BUILDING_SHARED_QUOTIENT
+ /* We are building this library */
+# define QUOTIENT_API Q_DECL_EXPORT
+# else
+ /* We are using this library */
+# define QUOTIENT_API Q_DECL_IMPORT
+# endif
+# endif
+
+# ifndef QUOTIENT_HIDDEN
+# define QUOTIENT_HIDDEN Q_DECL_HIDDEN
+# endif
+#endif
diff --git a/lib/room.h b/lib/room.h
index cbe3d1ad..e1e4fb91 100644
--- a/lib/room.h
+++ b/lib/room.h
@@ -45,7 +45,7 @@ class RedactEventJob;
* This is specifically tuned to work with QML exposing all traits as
* Q_PROPERTY values.
*/
-class FileTransferInfo {
+class QUOTIENT_API FileTransferInfo {
Q_GADGET
Q_PROPERTY(bool isUpload MEMBER isUpload CONSTANT)
Q_PROPERTY(bool active READ active CONSTANT)
@@ -73,7 +73,7 @@ public:
//! \brief Data structure for a room member's read receipt
//! \sa Room::lastReadReceipt
-class ReadReceipt {
+class QUOTIENT_API ReadReceipt {
Q_GADGET
Q_PROPERTY(QString eventId MEMBER eventId CONSTANT)
Q_PROPERTY(QDateTime timestamp MEMBER timestamp CONSTANT)
@@ -110,7 +110,7 @@ private:
Q_PROPERTY(Type type MEMBER type CONSTANT)
};
-class Room : public QObject {
+class QUOTIENT_API Room : public QObject {
Q_OBJECT
Q_PROPERTY(Connection* connection READ connection CONSTANT)
Q_PROPERTY(User* localUser READ localUser CONSTANT)
@@ -1044,7 +1044,7 @@ private:
void setJoinState(JoinState state);
};
-class MemberSorter {
+class QUOTIENT_API MemberSorter {
public:
explicit MemberSorter(const Room* r) : room(r) {}
diff --git a/lib/settings.h b/lib/settings.h
index 3cab8958..ff99d488 100644
--- a/lib/settings.h
+++ b/lib/settings.h
@@ -3,6 +3,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtCore/QSettings>
#include <QtCore/QUrl>
#include <QtCore/QVector>
@@ -11,7 +13,7 @@ class QVariant;
namespace Quotient {
-class Settings : public QSettings {
+class QUOTIENT_API Settings : public QSettings {
Q_OBJECT
public:
/// Add a legacy organisation/application name to migrate settings from
@@ -76,7 +78,7 @@ protected:
QSettings legacySettings { legacyOrganizationName, legacyApplicationName };
};
-class SettingsGroup : public Settings {
+class QUOTIENT_API SettingsGroup : public Settings {
public:
explicit SettingsGroup(QString path, QObject* parent = nullptr)
: Settings(parent)
@@ -124,7 +126,7 @@ private:
setValue(QStringLiteral(qsettingname), std::move(newValue)); \
}
-class AccountSettings : public SettingsGroup {
+class QUOTIENT_API AccountSettings : public SettingsGroup {
Q_OBJECT
Q_PROPERTY(QString userId READ userId CONSTANT)
QUO_DECLARE_SETTING(QString, deviceId, setDeviceId)
diff --git a/lib/ssosession.h b/lib/ssosession.h
index 72dd60c4..a658c043 100644
--- a/lib/ssosession.h
+++ b/lib/ssosession.h
@@ -3,6 +3,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtCore/QUrl>
#include <QtCore/QObject>
@@ -29,7 +31,7 @@ class Connection;
* connection->prepareForSso(initialDeviceName)->ssoUrl());
* \endcode
*/
-class SsoSession : public QObject {
+class QUOTIENT_API SsoSession : public QObject {
Q_OBJECT
Q_PROPERTY(QUrl ssoUrl READ ssoUrl CONSTANT)
Q_PROPERTY(QUrl callbackUrl READ callbackUrl CONSTANT)
diff --git a/lib/syncdata.h b/lib/syncdata.h
index 36d2e0bf..e29540c2 100644
--- a/lib/syncdata.h
+++ b/lib/syncdata.h
@@ -22,7 +22,7 @@ constexpr auto HighlightCountKey = "highlight_count"_ls;
* means that nothing has come from the server; heroes.value().isEmpty()
* means a peculiar case of a room with the only member - the current user.
*/
-struct RoomSummary {
+struct QUOTIENT_API RoomSummary {
Omittable<int> joinedMemberCount;
Omittable<int> invitedMemberCount;
Omittable<QStringList> heroes; //< mxids of users to take part in the room
diff --git a/lib/uri.h b/lib/uri.h
index d8b892b6..78cd27c8 100644
--- a/lib/uri.h
+++ b/lib/uri.h
@@ -23,7 +23,7 @@ namespace Quotient {
* its type, and obtain components, also in either unencoded (for displaying)
* or encoded (for APIs) form.
*/
-class Uri : private QUrl {
+class QUOTIENT_API Uri : private QUrl {
Q_GADGET
public:
enum Type : char {
diff --git a/lib/uriresolver.h b/lib/uriresolver.h
index ff97324a..9140046c 100644
--- a/lib/uriresolver.h
+++ b/lib/uriresolver.h
@@ -25,7 +25,7 @@ class User;
* gradual implementation. Derived classes are encouraged to override as many
* of them as possible.
*/
-class UriResolverBase {
+class QUOTIENT_API UriResolverBase {
public:
/*! \brief Resolve the resource and dispatch an action depending on its type
*
@@ -105,7 +105,7 @@ protected:
*
* \sa UriResolverBase, UriDispatcher
*/
-UriResolveResult
+QUOTIENT_API UriResolveResult
visitResource(Connection* account, const Uri& uri,
std::function<UriResolveResult(User*, QString)> userHandler,
std::function<void(Room*, QString)> roomEventHandler,
@@ -141,7 +141,7 @@ inline UriResolveResult checkResource(Connection* account, const Uri& uri)
* synchronously - the returned value is the result of resolving the URI,
* not acting on it.
*/
-class UriDispatcher : public QObject, public UriResolverBase {
+class QUOTIENT_API UriDispatcher : public QObject, public UriResolverBase {
Q_OBJECT
public:
explicit UriDispatcher(QObject* parent = nullptr) : QObject(parent) {}
diff --git a/lib/user.h b/lib/user.h
index 78b72bf2..435304ce 100644
--- a/lib/user.h
+++ b/lib/user.h
@@ -5,6 +5,7 @@
#pragma once
#include "avatar.h"
+#include "quotient_export.h"
#include <QtCore/QObject>
@@ -13,7 +14,7 @@ class Connection;
class Room;
class RoomMemberEvent;
-class User : public QObject {
+class QUOTIENT_API User : public QObject {
Q_OBJECT
Q_PROPERTY(QString id READ id CONSTANT)
Q_PROPERTY(bool isGuest READ isGuest CONSTANT)
diff --git a/lib/util.h b/lib/util.h
index 97f0ecbc..399f93c2 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -4,6 +4,8 @@
#pragma once
+#include "quotient_export.h"
+
#include <QtCore/QLatin1String>
#include <QtCore/QHashFunctions>
@@ -244,26 +246,26 @@ inline std::pair<InputIt, ForwardIt> findFirstOf(InputIt first, InputIt last,
}
/** Convert what looks like a URL or a Matrix ID to an HTML hyperlink */
-void linkifyUrls(QString& htmlEscapedText);
+QUOTIENT_API void linkifyUrls(QString& htmlEscapedText);
/** Sanitize the text before showing in HTML
*
* This does toHtmlEscaped() and removes Unicode BiDi marks.
*/
-QString sanitized(const QString& plainText);
+QUOTIENT_API QString sanitized(const QString& plainText);
/** Pretty-print plain text into HTML
*
* This includes HTML escaping of <,>,",& and calling linkifyUrls()
*/
-QString prettyPrint(const QString& plainText);
+QUOTIENT_API QString prettyPrint(const QString& plainText);
/** Return a path to cache directory after making sure that it exists
*
* The returned path has a trailing slash, clients don't need to append it.
* \param dir path to cache directory relative to the standard cache path
*/
-QString cacheLocation(const QString& dirName);
+QUOTIENT_API QString cacheLocation(const QString& dirName);
/** Hue color component of based of the hash of the string.
*
@@ -272,13 +274,13 @@ QString cacheLocation(const QString& dirName);
* Naming and range are the same as QColor's hueF method:
* https://doc.qt.io/qt-5/qcolor.html#integer-vs-floating-point-precision
*/
-qreal stringToHueF(const QString& s);
+QUOTIENT_API qreal stringToHueF(const QString& s);
/** Extract the serverpart from MXID */
-QString serverPart(const QString& mxId);
+QUOTIENT_API QString serverPart(const QString& mxId);
-QString versionString();
-int majorVersion();
-int minorVersion();
-int patchVersion();
+QUOTIENT_API QString versionString();
+QUOTIENT_API int majorVersion();
+QUOTIENT_API int minorVersion();
+QUOTIENT_API int patchVersion();
} // namespace Quotient
diff --git a/quotest/CMakeLists.txt b/quotest/CMakeLists.txt
index cb41141d..ec305620 100644
--- a/quotest/CMakeLists.txt
+++ b/quotest/CMakeLists.txt
@@ -8,6 +8,11 @@ find_package(${Qt} COMPONENTS Concurrent)
add_executable(quotest ${quotest_SRCS})
target_link_libraries(quotest PRIVATE ${Qt}::Core ${Qt}::Test ${Qt}::Concurrent ${PROJECT_NAME})
+set_target_properties(quotest PROPERTIES
+ VISIBILITY_INLINES_HIDDEN ON
+ CXX_VISIBILITY_PRESET hidden
+)
+
if (MSVC)
target_compile_options(quotest PUBLIC /EHsc /W4
/wd4100 /wd4127 /wd4242 /wd4244 /wd4245 /wd4267 /wd4365 /wd4456 /wd4459
diff --git a/quotest/quotest.cpp b/quotest/quotest.cpp
index 7bd9c5c3..5a5642fe 100644
--- a/quotest/quotest.cpp
+++ b/quotest/quotest.cpp
@@ -101,6 +101,7 @@ private slots:
TEST_DECL(sendMessage)
TEST_DECL(sendReaction)
TEST_DECL(sendFile)
+ TEST_DECL(sendCustomEvent)
TEST_DECL(setTopic)
TEST_DECL(changeName)
TEST_DECL(sendAndRedact)
@@ -125,6 +126,7 @@ private:
[[nodiscard]] bool checkRedactionOutcome(const QByteArray& thisTest,
const QString& evtIdToRedact);
+ template <class EventT>
[[nodiscard]] bool validatePendingEvent(const QString& txnId);
[[nodiscard]] bool checkDirectChat() const;
void finishTest(const TestToken& token, bool condition, const char* file,
@@ -152,12 +154,14 @@ void TestSuite::doTest(const QByteArray& testName)
Q_ARG(TestToken, testName));
}
+template <class EventT>
bool TestSuite::validatePendingEvent(const QString& txnId)
{
auto it = targetRoom->findPendingEvent(txnId);
return it != targetRoom->pendingEvents().end()
&& it->deliveryStatus() == EventStatus::Submitted
- && (*it)->transactionId() == txnId;
+ && (*it)->transactionId() == txnId && is<EventT>(**it)
+ && (*it)->matrixType() == EventT::matrixTypeId();
}
void TestSuite::finishTest(const TestToken& token, bool condition,
@@ -341,7 +345,7 @@ TEST_IMPL(loadMembers)
TEST_IMPL(sendMessage)
{
auto txnId = targetRoom->postPlainText("Hello, " % origin % " is here");
- if (!validatePendingEvent(txnId)) {
+ if (!validatePendingEvent<RoomMessageEvent>(txnId)) {
clog << "Invalid pending event right after submitting" << endl;
FAIL_TEST();
}
@@ -367,7 +371,7 @@ TEST_IMPL(sendReaction)
const auto targetEvtId = targetRoom->messageEvents().back()->id();
const auto key = QStringLiteral("+1");
const auto txnId = targetRoom->postReaction(targetEvtId, key);
- if (!validatePendingEvent(txnId)) {
+ if (!validatePendingEvent<ReactionEvent>(txnId)) {
clog << "Invalid pending event right after submitting" << endl;
FAIL_TEST();
}
@@ -409,7 +413,7 @@ TEST_IMPL(sendFile)
clog << "Sending file " << tfName.toStdString() << endl;
const auto txnId = targetRoom->postFile(
"Test file", new EventContent::FileContent(tfi));
- if (!validatePendingEvent(txnId)) {
+ if (!validatePendingEvent<RoomMessageEvent>(txnId)) {
clog << "Invalid pending event right after submitting" << endl;
tf->deleteLater();
FAIL_TEST();
@@ -518,6 +522,50 @@ bool TestSuite::checkFileSendingOutcome(const TestToken& thisTest,
return true;
}
+class CustomEvent : public RoomEvent {
+public:
+ DEFINE_EVENT_TYPEID("quotest.custom", CustomEvent)
+
+ CustomEvent(const QJsonObject& jo)
+ : RoomEvent(typeId(), jo)
+ {}
+ CustomEvent(int testValue)
+ : RoomEvent(typeId(),
+ basicEventJson(matrixTypeId(),
+ QJsonObject { { "testValue"_ls,
+ toJson(testValue) } }))
+ {}
+
+ auto testValue() const { return contentPart<int>("testValue"_ls); }
+};
+REGISTER_EVENT_TYPE(CustomEvent)
+
+TEST_IMPL(sendCustomEvent)
+{
+ auto txnId = targetRoom->postEvent(new CustomEvent(42));
+ if (!validatePendingEvent<CustomEvent>(txnId)) {
+ clog << "Invalid pending event right after submitting" << endl;
+ FAIL_TEST();
+ }
+ connectUntil(
+ targetRoom, &Room::pendingEventAboutToMerge, this,
+ [this, thisTest, txnId](const RoomEvent* evt, int pendingIdx) {
+ const auto& pendingEvents = targetRoom->pendingEvents();
+ Q_ASSERT(pendingIdx >= 0 && pendingIdx < int(pendingEvents.size()));
+
+ if (evt->transactionId() != txnId)
+ return false;
+
+ return switchOnType(*evt,
+ [this, thisTest, &evt](const CustomEvent& e) {
+ FINISH_TEST(!evt->id().isEmpty() && e.testValue() == 42);
+ },
+ [this, thisTest] (const RoomEvent&) { FAIL_TEST(); });
+ });
+ return false;
+
+}
+
TEST_IMPL(setTopic)
{
const auto newTopic = connection()->generateTxnId(); // Just a way to make
@@ -567,7 +615,6 @@ TEST_IMPL(changeName)
return false;
}
-
TEST_IMPL(showLocalUsername)
{
auto* const localUser = connection()->user();