mirror of
https://github.com/QuasarApp/QtAndroidTools.git
synced 2025-04-27 05:24:31 +00:00
Improved tool for manage consent form
This commit is contained in:
parent
cb38e39286
commit
9441f17c9b
@ -55,6 +55,7 @@
|
||||
<li><a href="#GoogleAccount">GoogleAccount</a></li>
|
||||
<li><a href="#GoogleDrive">GoogleDrive</a></li>
|
||||
<li><a href="#Sharing">Sharing</a></li>
|
||||
<li><a href="#UserMessagingPlatform">UserMessagingPlatform</a></li>
|
||||
<li><a href="#System">System</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
@ -87,7 +88,8 @@
|
||||
QTAT_PLAY_STORE \
|
||||
QTAT_GOOGLE_ACCOUNT \
|
||||
QTAT_GOOGLE_DRIVE \
|
||||
QTAT_SHARING</pre>
|
||||
QTAT_SHARING \
|
||||
QTAT_USER_MESSAGING_PLATFORM</pre>
|
||||
</li>
|
||||
<li>In the <i>main()</i> body insert the call for initialize the library<br />
|
||||
<pre class="prettyprint">QtAndroidTools::initializeQmlTools();</pre>
|
||||
@ -704,6 +706,45 @@ QtAndroidSharing.getReceivedMultipleSharedBinaryData()</pre>
|
||||
<pre>QtAndroidSharing.shareFile(fileAvailable, mimeType, filePath)</pre>
|
||||
<p>In case the user want the file you have to set the <i>fileAvailable</i> as true and provide the other params. In the opposite case (the user refused) you have to call this function by set the first param as false without provide the other params.</p>
|
||||
</div>
|
||||
<div class="section-txt" id="UserMessagingPlatform">
|
||||
<h3>UserMessagingPlatform</h3>
|
||||
<p>Under the Google <a href="https://www.google.com/about/company/user-consent-policy/" target="_blank">EU User Consent Policy</a>, you must make certain disclosures to your users in the European Economic Area (EEA) along with the UK and obtain their consent to use cookies or other local storage, where legally required, and to use personal data (such as AdID) to serve ads. This policy reflects the requirements of the EU ePrivacy Directive and the General Data Protection Regulation (GDPR).</p>
|
||||
<p>This tool support the use of the UMP SDK but for a clear explanation about how to use this SDK and how to configure the consent form you have to read the official guide <a href="https://developers.google.com/admob/ump/android/quick-start" target="_blank">here</a>. At first you must to request the consent form that can be or not be available for the zone your current user is:</p>
|
||||
<pre class="prettyprint">Connections {
|
||||
target: QtAndroidUserMessagingPlatform
|
||||
function onConsentFormRequestResult(eventId)
|
||||
{
|
||||
switch(eventId)
|
||||
{
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_INFO_UPDATE_FAILURE:
|
||||
....
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_NOT_AVAILABLE:
|
||||
....
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_SUCCESS:
|
||||
....
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_FAILURE:
|
||||
....
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QtAndroidUserMessagingPlatform.requestConsentForm()</pre>
|
||||
|
||||
<p>Once request process finish the signal <i>consentFormRequestResult()</i> is emitted with the results. Any event different from CONSENT_FORM_LOAD_SUCCESS means the form is not available for various reasons. Once obtained the form is necessary to check if it must be showed to the user. You can get such information as follow:</p>
|
||||
<pre>QtAndroidUserMessagingPlatform.consentStatus()</pre>
|
||||
<p>Possible returned values are:</p>
|
||||
<pre>QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_UNKNOWN
|
||||
QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_REQUIRED
|
||||
QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_NOT_REQUIRED
|
||||
QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_OBTAINED</pre>
|
||||
<p>If the status is different from CONSENT_FORM_STATUS_REQUIRED you don't need to show the form. On the contrary, in case of form required or if the user want to change his preferences you can show the form using the call:</p>
|
||||
<pre>QtAndroidUserMessagingPlatform.showConsentForm()</pre>
|
||||
<p>The event <i>consentFormClosed()</i> will inform you when the user closed the form and your app is ready to go. After the user accepted the form some data will be saved in the device and the form will not be required anymore. However if you want to reset these data for restart from scratch you can use the call:</p>
|
||||
<pre>QtAndroidUserMessagingPlatform.resetConsentInformation()</pre>
|
||||
<p>This will clean all saved data.</p>
|
||||
<div class="section-txt" id="System">
|
||||
<h3>System</h3>
|
||||
<p>Currently this tool export only the system paths.</p>
|
||||
|
@ -34,7 +34,8 @@ QAndroidUserMessagingPlatform::QAndroidUserMessagingPlatform() : m_javaUserMessa
|
||||
if(m_javaUserMessagingPlatform.isValid())
|
||||
{
|
||||
const JNINativeMethod jniMethod[] = {
|
||||
{"consentFormShowResult", "(I)V", reinterpret_cast<void *>(&QAndroidUserMessagingPlatform::deviceConsentFormShowResult)},
|
||||
{"consentFormRequestResult", "(I)V", reinterpret_cast<void*>(&QAndroidUserMessagingPlatform::deviceConsentFormRequestResult)},
|
||||
{"consentFormClosed", "()V", reinterpret_cast<void*>(&QAndroidUserMessagingPlatform::deviceConsentFormClosed)},
|
||||
};
|
||||
QAndroidJniEnvironment jniEnv;
|
||||
jclass objectClass;
|
||||
@ -58,25 +59,54 @@ QAndroidUserMessagingPlatform* QAndroidUserMessagingPlatform::instance()
|
||||
return m_pInstance;
|
||||
}
|
||||
|
||||
void QAndroidUserMessagingPlatform::deviceConsentFormShowResult(JNIEnv *env, jobject thiz, int eventId)
|
||||
void QAndroidUserMessagingPlatform::deviceConsentFormRequestResult(JNIEnv *env, jobject thiz, int eventId)
|
||||
{
|
||||
Q_UNUSED(env)
|
||||
Q_UNUSED(thiz)
|
||||
|
||||
if(m_pInstance != nullptr)
|
||||
{
|
||||
Q_EMIT m_pInstance->consentFormShowResult(eventId);
|
||||
Q_EMIT m_pInstance->consentFormRequestResult(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidUserMessagingPlatform::showConsentFormIfRequired()
|
||||
void QAndroidUserMessagingPlatform::deviceConsentFormClosed(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
Q_UNUSED(env)
|
||||
Q_UNUSED(thiz)
|
||||
|
||||
if(m_pInstance != nullptr)
|
||||
{
|
||||
Q_EMIT m_pInstance->consentFormClosed();
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidUserMessagingPlatform::requestConsentForm()
|
||||
{
|
||||
if(m_javaUserMessagingPlatform.isValid())
|
||||
{
|
||||
m_javaUserMessagingPlatform.callMethod<void>("showConsentFormIfRequired");
|
||||
m_javaUserMessagingPlatform.callMethod<void>("requestConsentForm");
|
||||
}
|
||||
}
|
||||
|
||||
int QAndroidUserMessagingPlatform::consentStatus()
|
||||
{
|
||||
if(m_javaUserMessagingPlatform.isValid())
|
||||
{
|
||||
return m_javaUserMessagingPlatform.callMethod<jint>("consentStatus");
|
||||
}
|
||||
return CONSENT_FORM_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
bool QAndroidUserMessagingPlatform::showConsentForm()
|
||||
{
|
||||
if(m_javaUserMessagingPlatform.isValid())
|
||||
{
|
||||
return m_javaUserMessagingPlatform.callMethod<jboolean>("showConsentForm");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QAndroidUserMessagingPlatform::resetConsentInformation()
|
||||
{
|
||||
if(m_javaUserMessagingPlatform.isValid())
|
||||
|
@ -30,35 +30,43 @@ class QAndroidUserMessagingPlatform : public QObject
|
||||
{
|
||||
Q_DISABLE_COPY(QAndroidUserMessagingPlatform)
|
||||
Q_ENUMS(CONSENT_STATUS)
|
||||
Q_ENUMS(REQUEST_RESULT)
|
||||
Q_OBJECT
|
||||
|
||||
QAndroidUserMessagingPlatform();
|
||||
|
||||
public:
|
||||
enum CONSENT_STATUS
|
||||
{
|
||||
CONSENT_FORM_STATUS_UNKNOWN = 0,
|
||||
CONSENT_FORM_STATUS_REQUIRED = 1,
|
||||
CONSENT_FORM_STATUS_NOT_REQUIRED = 2,
|
||||
CONSENT_FORM_STATUS_OBTAINED = 3,
|
||||
};
|
||||
enum REQUEST_RESULT
|
||||
{
|
||||
CONSENT_FORM_INFO_UPDATE_FAILURE = 0,
|
||||
CONSENT_FORM_NOT_AVAILABLE = 1,
|
||||
CONSENT_FORM_STATUS_UNKNOWN = 2,
|
||||
CONSENT_FORM_STATUS_REQUIRED = 3,
|
||||
CONSENT_FORM_STATUS_NOT_REQUIRED = 4,
|
||||
CONSENT_FORM_STATUS_OBTAINED = 5,
|
||||
CONSENT_FORM_LOAD_FAILURE = 6,
|
||||
CONSENT_FORM_DISMISSED = 7
|
||||
CONSENT_FORM_LOAD_SUCCESS = 2,
|
||||
CONSENT_FORM_LOAD_FAILURE = 3
|
||||
};
|
||||
|
||||
static QObject* qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine);
|
||||
static QAndroidUserMessagingPlatform* instance();
|
||||
|
||||
Q_INVOKABLE void showConsentFormIfRequired();
|
||||
Q_INVOKABLE void requestConsentForm();
|
||||
Q_INVOKABLE int consentStatus();
|
||||
Q_INVOKABLE bool showConsentForm();
|
||||
Q_INVOKABLE void resetConsentInformation();
|
||||
|
||||
Q_SIGNALS:
|
||||
void consentFormShowResult(int eventId);
|
||||
void consentFormRequestResult(int eventId);
|
||||
void consentFormClosed();
|
||||
|
||||
private:
|
||||
const QAndroidJniObject m_javaUserMessagingPlatform;
|
||||
static QAndroidUserMessagingPlatform *m_pInstance;
|
||||
|
||||
static void deviceConsentFormShowResult(JNIEnv *env, jobject thiz, int eventId);
|
||||
static void deviceConsentFormRequestResult(JNIEnv *env, jobject thiz, int eventId);
|
||||
static void deviceConsentFormClosed(JNIEnv *env, jobject thiz);
|
||||
};
|
||||
|
@ -40,6 +40,7 @@ public class AndroidUserMessagingPlatform
|
||||
private final ConsentInformation mConsentInformation;
|
||||
private final ConsentListener mConsentListener;
|
||||
private final Activity mActivityInstance;
|
||||
private int mConsentStatus = ConsentInformation.ConsentStatus.UNKNOWN;
|
||||
private ConsentForm mConsentForm = null;
|
||||
|
||||
public AndroidUserMessagingPlatform(Activity activityInstance)
|
||||
@ -49,42 +50,7 @@ public class AndroidUserMessagingPlatform
|
||||
mActivityInstance = activityInstance;
|
||||
}
|
||||
|
||||
public void showConsentFormIfRequired()
|
||||
{
|
||||
requestConsentInfoUpdate();
|
||||
}
|
||||
|
||||
public void resetConsentInformation()
|
||||
{
|
||||
mConsentInformation.reset();
|
||||
}
|
||||
|
||||
private void requestConsentInfoUpdate()
|
||||
{
|
||||
final ConsentRequestParameters params = new ConsentRequestParameters.Builder().build();
|
||||
mConsentInformation.requestConsentInfoUpdate(mActivityInstance, params, mConsentListener, mConsentListener);
|
||||
}
|
||||
|
||||
private void loadConsentForm()
|
||||
{
|
||||
if(mConsentInformation.isConsentFormAvailable())
|
||||
{
|
||||
mActivityInstance.runOnUiThread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
UserMessagingPlatform.loadConsentForm(mActivityInstance, mConsentListener, mConsentListener);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
consentFormShowResult(CONSENT_FORM_NOT_AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void showConsentForm()
|
||||
public boolean showConsentForm()
|
||||
{
|
||||
if(mConsentForm != null)
|
||||
{
|
||||
@ -96,11 +62,45 @@ public class AndroidUserMessagingPlatform
|
||||
mConsentForm.show(mActivityInstance, mConsentListener);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resetConsentInformation()
|
||||
{
|
||||
mConsentInformation.reset();
|
||||
}
|
||||
|
||||
public void requestConsentForm()
|
||||
{
|
||||
final ConsentRequestParameters params = new ConsentRequestParameters.Builder().build();
|
||||
mConsentInformation.requestConsentInfoUpdate(mActivityInstance, params, mConsentListener, mConsentListener);
|
||||
}
|
||||
|
||||
public int consentStatus()
|
||||
{
|
||||
int status = CONSENT_FORM_STATUS_UNKNOWN;
|
||||
|
||||
switch(mConsentStatus)
|
||||
{
|
||||
consentFormShowResult(CONSENT_FORM_NOT_AVAILABLE);
|
||||
case ConsentInformation.ConsentStatus.REQUIRED:
|
||||
status = CONSENT_FORM_STATUS_REQUIRED;
|
||||
break;
|
||||
case ConsentInformation.ConsentStatus.NOT_REQUIRED:
|
||||
status = CONSENT_FORM_STATUS_NOT_REQUIRED;
|
||||
break;
|
||||
case ConsentInformation.ConsentStatus.OBTAINED:
|
||||
status = CONSENT_FORM_STATUS_OBTAINED;
|
||||
break;
|
||||
case ConsentInformation.ConsentStatus.UNKNOWN:
|
||||
status = CONSENT_FORM_STATUS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
private class ConsentListener implements ConsentInformation.OnConsentInfoUpdateSuccessListener,
|
||||
@ -114,69 +114,59 @@ public class AndroidUserMessagingPlatform
|
||||
{
|
||||
if(mConsentInformation.isConsentFormAvailable())
|
||||
{
|
||||
loadConsentForm();
|
||||
mActivityInstance.runOnUiThread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
UserMessagingPlatform.loadConsentForm(mActivityInstance, mConsentListener, mConsentListener);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
consentFormShowResult(CONSENT_FORM_NOT_AVAILABLE);
|
||||
consentFormRequestResult(CONSENT_FORM_NOT_AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsentInfoUpdateFailure(FormError formError)
|
||||
{
|
||||
consentFormShowResult(CONSENT_FORM_INFO_UPDATE_FAILURE);
|
||||
consentFormRequestResult(CONSENT_FORM_INFO_UPDATE_FAILURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsentFormLoadSuccess(ConsentForm consentForm)
|
||||
{
|
||||
final int consentStatus = mConsentInformation.getConsentStatus();
|
||||
|
||||
mConsentStatus = mConsentInformation.getConsentStatus();
|
||||
mConsentForm = consentForm;
|
||||
if(consentStatus == ConsentInformation.ConsentStatus.REQUIRED)
|
||||
{
|
||||
showConsentForm();
|
||||
}
|
||||
else
|
||||
{
|
||||
int eventId = CONSENT_FORM_STATUS_UNKNOWN;
|
||||
|
||||
switch(consentStatus)
|
||||
{
|
||||
case ConsentInformation.ConsentStatus.NOT_REQUIRED:
|
||||
eventId = CONSENT_FORM_STATUS_NOT_REQUIRED;
|
||||
break;
|
||||
case ConsentInformation.ConsentStatus.OBTAINED:
|
||||
eventId = CONSENT_FORM_STATUS_OBTAINED;
|
||||
break;
|
||||
}
|
||||
|
||||
consentFormShowResult(eventId);
|
||||
}
|
||||
consentFormRequestResult(CONSENT_FORM_LOAD_SUCCESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsentFormLoadFailure(FormError formError)
|
||||
{
|
||||
consentFormShowResult(CONSENT_FORM_LOAD_FAILURE);
|
||||
consentFormRequestResult(CONSENT_FORM_LOAD_FAILURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsentFormDismissed(@Nullable FormError formError)
|
||||
{
|
||||
consentFormShowResult(CONSENT_FORM_DISMISSED);
|
||||
consentFormClosed();
|
||||
}
|
||||
}
|
||||
|
||||
private static final int CONSENT_FORM_INFO_UPDATE_FAILURE = 0;
|
||||
private static final int CONSENT_FORM_NOT_AVAILABLE = 1;
|
||||
private static final int CONSENT_FORM_STATUS_UNKNOWN = 2;
|
||||
private static final int CONSENT_FORM_STATUS_REQUIRED = 3;
|
||||
private static final int CONSENT_FORM_STATUS_NOT_REQUIRED = 4;
|
||||
private static final int CONSENT_FORM_STATUS_OBTAINED = 5;
|
||||
private static final int CONSENT_FORM_LOAD_FAILURE = 6;
|
||||
private static final int CONSENT_FORM_DISMISSED = 7;
|
||||
private static final int CONSENT_FORM_LOAD_SUCCESS = 2;
|
||||
private static final int CONSENT_FORM_LOAD_FAILURE = 3;
|
||||
|
||||
private static native void consentFormShowResult(int eventId);
|
||||
private static final int CONSENT_FORM_STATUS_UNKNOWN = 0;
|
||||
private static final int CONSENT_FORM_STATUS_REQUIRED = 1;
|
||||
private static final int CONSENT_FORM_STATUS_NOT_REQUIRED = 2;
|
||||
private static final int CONSENT_FORM_STATUS_OBTAINED = 3;
|
||||
|
||||
private static native void consentFormRequestResult(int eventId);
|
||||
private static native void consentFormClosed();
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ Page {
|
||||
|
||||
Connections {
|
||||
target: QtAndroidUserMessagingPlatform
|
||||
function onConsentFormShowResult(eventId)
|
||||
function onConsentFormRequestResult(eventId)
|
||||
{
|
||||
switch(eventId)
|
||||
{
|
||||
@ -19,26 +19,17 @@ Page {
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_NOT_AVAILABLE:
|
||||
consentFormShowResult.text = "CONSENT_FORM_NOT_AVAILABLE";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_UNKNOWN:
|
||||
consentFormShowResult.text = "CONSENT_FORM_STATUS_UNKNOWN";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_REQUIRED:
|
||||
consentFormShowResult.text = "CONSENT_FORM_STATUS_REQUIRED";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_NOT_REQUIRED:
|
||||
consentFormShowResult.text = "CONSENT_FORM_STATUS_NOT_REQUIRED";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_OBTAINED:
|
||||
consentFormShowResult.text = "CONSENT_FORM_STATUS_OBTAINED";
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_SUCCESS:
|
||||
consentFormShowResult.text = "CONSENT_FORM_LOAD_SUCCESS";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_FAILURE:
|
||||
consentFormShowResult.text = "CONSENT_FORM_LOAD_FAILURE";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_DISMISSED:
|
||||
consentFormShowResult.text = "CONSENT_FORM_DISMISSED";
|
||||
break;
|
||||
}
|
||||
}
|
||||
function onConsentFormClosed()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
@ -46,7 +37,7 @@ Page {
|
||||
spacing: 5
|
||||
|
||||
Label {
|
||||
id: consentFormShowResult
|
||||
id: consentFormRequestResult
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 15
|
||||
@ -54,8 +45,45 @@ Page {
|
||||
}
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "showConsentFormIfRequired"
|
||||
onClicked: QtAndroidUserMessagingPlatform.showConsentFormIfRequired()
|
||||
text: "requestConsentForm"
|
||||
onClicked: QtAndroidUserMessagingPlatform.requestConsentForm()
|
||||
}
|
||||
|
||||
Label {
|
||||
id: consentStatus
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 15
|
||||
text: "-----"
|
||||
}
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "consentStatus"
|
||||
onClicked: {
|
||||
var status = QtAndroidUserMessagingPlatform.consentStatus();
|
||||
|
||||
switch(eventId)
|
||||
{
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_UNKNOWN:
|
||||
consentStatus.text = "CONSENT_FORM_STATUS_UNKNOWN";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_REQUIRED:
|
||||
consentStatus.text = "CONSENT_FORM_STATUS_REQUIRED";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_NOT_REQUIRED:
|
||||
consentStatus.text = "CONSENT_FORM_STATUS_NOT_REQUIRED";
|
||||
break;
|
||||
case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_OBTAINED:
|
||||
consentStatus.text = "CONSENT_FORM_STATUS_OBTAINED";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "showConsentForm"
|
||||
onClicked: QtAndroidUserMessagingPlatform.showConsentForm()
|
||||
}
|
||||
|
||||
Button {
|
||||
|
Loading…
x
Reference in New Issue
Block a user