Merge "Fixes to json output"
This commit is contained in:
commit
30ff0898fd
3 changed files with 63 additions and 115 deletions
|
@ -237,10 +237,6 @@ public class PointerTracker {
|
||||||
+ " ignoreModifier=" + ignoreModifierKey
|
+ " ignoreModifier=" + ignoreModifierKey
|
||||||
+ " enabled=" + key.isEnabled());
|
+ " enabled=" + key.isEnabled());
|
||||||
}
|
}
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
|
||||||
ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key,
|
|
||||||
ignoreModifierKey);
|
|
||||||
}
|
|
||||||
if (ignoreModifierKey) {
|
if (ignoreModifierKey) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,9 +305,6 @@ public class KeyboardState {
|
||||||
Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code)
|
Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code)
|
||||||
+ " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this);
|
+ " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this);
|
||||||
}
|
}
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
|
||||||
ResearchLogger.keyboardState_onPressKey(code, this);
|
|
||||||
}
|
|
||||||
if (code == Keyboard.CODE_SHIFT) {
|
if (code == Keyboard.CODE_SHIFT) {
|
||||||
onPressShift();
|
onPressShift();
|
||||||
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
|
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
|
||||||
|
@ -341,9 +338,6 @@ public class KeyboardState {
|
||||||
Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code)
|
Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code)
|
||||||
+ " sliding=" + withSliding + " " + this);
|
+ " sliding=" + withSliding + " " + this);
|
||||||
}
|
}
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
|
||||||
ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding);
|
|
||||||
}
|
|
||||||
if (code == Keyboard.CODE_SHIFT) {
|
if (code == Keyboard.CODE_SHIFT) {
|
||||||
onReleaseShift(withSliding);
|
onReleaseShift(withSliding);
|
||||||
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
|
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
|
||||||
|
@ -375,9 +369,6 @@ public class KeyboardState {
|
||||||
if (DEBUG_EVENT) {
|
if (DEBUG_EVENT) {
|
||||||
Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this);
|
Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this);
|
||||||
}
|
}
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
|
||||||
ResearchLogger.keyboardState_onLongPressTimeout(code, this);
|
|
||||||
}
|
|
||||||
if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) {
|
if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) {
|
||||||
mLongPressShiftLockFired = true;
|
mLongPressShiftLockFired = true;
|
||||||
mSwitchActions.hapticAndAudioFeedback(code);
|
mSwitchActions.hapticAndAudioFeedback(code);
|
||||||
|
@ -509,9 +500,6 @@ public class KeyboardState {
|
||||||
if (DEBUG_EVENT) {
|
if (DEBUG_EVENT) {
|
||||||
Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
|
Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
|
||||||
}
|
}
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
|
||||||
ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this);
|
|
||||||
}
|
|
||||||
// Switch back to the previous keyboard mode if the user cancels sliding input.
|
// Switch back to the previous keyboard mode if the user cancels sliding input.
|
||||||
if (isSinglePointer) {
|
if (isSinglePointer) {
|
||||||
if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
|
if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
|
||||||
|
@ -543,9 +531,6 @@ public class KeyboardState {
|
||||||
+ " single=" + isSinglePointer
|
+ " single=" + isSinglePointer
|
||||||
+ " autoCaps=" + autoCaps + " " + this);
|
+ " autoCaps=" + autoCaps + " " + this);
|
||||||
}
|
}
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
|
||||||
ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mSwitchState) {
|
switch (mSwitchState) {
|
||||||
case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
|
case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.Editor;
|
import android.content.SharedPreferences.Editor;
|
||||||
import android.inputmethodservice.InputMethodService;
|
import android.inputmethodservice.InputMethodService;
|
||||||
|
@ -35,7 +37,8 @@ import android.view.inputmethod.InputConnection;
|
||||||
import com.android.inputmethod.keyboard.Key;
|
import com.android.inputmethod.keyboard.Key;
|
||||||
import com.android.inputmethod.keyboard.KeyDetector;
|
import com.android.inputmethod.keyboard.KeyDetector;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.keyboard.internal.KeyboardState;
|
import com.android.inputmethod.keyboard.KeyboardId;
|
||||||
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.define.ProductionFlag;
|
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
|
@ -68,7 +71,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
private static final JsonWriter NULL_JSON_WRITER = new JsonWriter(
|
private static final JsonWriter NULL_JSON_WRITER = new JsonWriter(
|
||||||
new OutputStreamWriter(new NullOutputStream()));
|
new OutputStreamWriter(new NullOutputStream()));
|
||||||
private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
|
private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
|
||||||
new SimpleDateFormat("yyyyMMDDHHmmss", Locale.US);
|
new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
|
||||||
|
|
||||||
// constants related to specific log points
|
// constants related to specific log points
|
||||||
private static final String WHITESPACE_SEPARATORS = " \t\n\r";
|
private static final String WHITESPACE_SEPARATORS = " \t\n\r";
|
||||||
|
@ -275,15 +278,19 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
final Object innerValue = entry.getValue();
|
final Object innerValue = entry.getValue();
|
||||||
if (innerValue == null) {
|
if (innerValue == null) {
|
||||||
mJsonWriter.nullValue();
|
mJsonWriter.nullValue();
|
||||||
|
} else if (innerValue instanceof Boolean) {
|
||||||
|
mJsonWriter.value((Boolean) innerValue);
|
||||||
|
} else if (innerValue instanceof Number) {
|
||||||
|
mJsonWriter.value((Number) innerValue);
|
||||||
} else {
|
} else {
|
||||||
mJsonWriter.value(innerValue.toString());
|
mJsonWriter.value(innerValue.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mJsonWriter.endObject();
|
mJsonWriter.endObject();
|
||||||
} else if (value instanceof Keyboard) {
|
} else if (value instanceof Key[]) {
|
||||||
Keyboard keyboard = (Keyboard) value;
|
Key[] keys = (Key[]) value;
|
||||||
mJsonWriter.beginArray();
|
mJsonWriter.beginArray();
|
||||||
for (Key key : keyboard.mKeys) {
|
for (Key key : keys) {
|
||||||
mJsonWriter.beginObject();
|
mJsonWriter.beginObject();
|
||||||
mJsonWriter.name("code").value(key.mCode);
|
mJsonWriter.name("code").value(key.mCode);
|
||||||
mJsonWriter.name("altCode").value(key.mAltCode);
|
mJsonWriter.name("altCode").value(key.mAltCode);
|
||||||
|
@ -294,6 +301,29 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
mJsonWriter.endObject();
|
mJsonWriter.endObject();
|
||||||
}
|
}
|
||||||
mJsonWriter.endArray();
|
mJsonWriter.endArray();
|
||||||
|
} else if (value instanceof SuggestedWords) {
|
||||||
|
SuggestedWords words = (SuggestedWords) value;
|
||||||
|
mJsonWriter.beginObject();
|
||||||
|
mJsonWriter.name("typedWordValid").value(words.mTypedWordValid);
|
||||||
|
mJsonWriter.name("hasAutoCorrectionCandidate")
|
||||||
|
.value(words.mHasAutoCorrectionCandidate);
|
||||||
|
mJsonWriter.name("isPunctuationSuggestions")
|
||||||
|
.value(words.mIsPunctuationSuggestions);
|
||||||
|
mJsonWriter.name("allowsToBeAutoCorrected")
|
||||||
|
.value(words.mAllowsToBeAutoCorrected);
|
||||||
|
mJsonWriter.name("isObsoleteSuggestions")
|
||||||
|
.value(words.mIsObsoleteSuggestions);
|
||||||
|
mJsonWriter.name("isPrediction")
|
||||||
|
.value(words.mIsPrediction);
|
||||||
|
mJsonWriter.name("words");
|
||||||
|
mJsonWriter.beginArray();
|
||||||
|
final int size = words.size();
|
||||||
|
for (int j = 0; j < size; j++) {
|
||||||
|
SuggestedWordInfo wordInfo = words.getWordInfo(j);
|
||||||
|
mJsonWriter.value(wordInfo.toString());
|
||||||
|
}
|
||||||
|
mJsonWriter.endArray();
|
||||||
|
mJsonWriter.endObject();
|
||||||
} else if (value == null) {
|
} else if (value == null) {
|
||||||
mJsonWriter.nullValue();
|
mJsonWriter.nullValue();
|
||||||
} else {
|
} else {
|
||||||
|
@ -370,72 +400,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
getInstance().writeEvent(EVENTKEYS_CORRECTION, values);
|
getInstance().writeEvent(EVENTKEYS_CORRECTION, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_STATECHANGE = {
|
|
||||||
"STATECHANGE", "subgroup", "details"
|
|
||||||
};
|
|
||||||
public static void logStateChange(final String subgroup, final String details) {
|
|
||||||
final Object[] values = {
|
|
||||||
subgroup, details
|
|
||||||
};
|
|
||||||
getInstance().writeEvent(EVENTKEYS_STATECHANGE, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_KEYBOARDSTATE_ONCANCELINPUT = {
|
|
||||||
"KEYBOARDSTATE_ONCANCELINPUT", "isSinglePointer", "keyboardState"
|
|
||||||
};
|
|
||||||
public static void keyboardState_onCancelInput(final boolean isSinglePointer,
|
|
||||||
final KeyboardState keyboardState) {
|
|
||||||
final Object[] values = {
|
|
||||||
isSinglePointer, keyboardState.toString()
|
|
||||||
};
|
|
||||||
getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONCANCELINPUT, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_KEYBOARDSTATE_ONCODEINPUT = {
|
|
||||||
"KEYBOARDSTATE_ONCODEINPUT", "code", "isSinglePointer", "autoCaps", "keyboardState"
|
|
||||||
};
|
|
||||||
public static void keyboardState_onCodeInput(
|
|
||||||
final int code, final boolean isSinglePointer, final int autoCaps,
|
|
||||||
final KeyboardState keyboardState) {
|
|
||||||
final Object[] values = {
|
|
||||||
Keyboard.printableCode(code), isSinglePointer, autoCaps, keyboardState.toString()
|
|
||||||
};
|
|
||||||
getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONCODEINPUT, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_KEYBOARDSTATE_ONLONGPRESSTIMEOUT = {
|
|
||||||
"KEYBOARDSTATE_ONLONGPRESSTIMEOUT", "code", "keyboardState"
|
|
||||||
};
|
|
||||||
public static void keyboardState_onLongPressTimeout(final int code,
|
|
||||||
final KeyboardState keyboardState) {
|
|
||||||
final Object[] values = {
|
|
||||||
Keyboard.printableCode(code), keyboardState.toString()
|
|
||||||
};
|
|
||||||
getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONLONGPRESSTIMEOUT, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_KEYBOARDSTATE_ONPRESSKEY = {
|
|
||||||
"KEYBOARDSTATE_ONPRESSKEY", "code", "keyboardState"
|
|
||||||
};
|
|
||||||
public static void keyboardState_onPressKey(final int code,
|
|
||||||
final KeyboardState keyboardState) {
|
|
||||||
final Object[] values = {
|
|
||||||
Keyboard.printableCode(code), keyboardState.toString()
|
|
||||||
};
|
|
||||||
getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONPRESSKEY, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_KEYBOARDSTATE_ONRELEASEKEY = {
|
|
||||||
"KEYBOARDSTATE_ONRELEASEKEY", "code", "withSliding", "keyboardState"
|
|
||||||
};
|
|
||||||
public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code,
|
|
||||||
final boolean withSliding) {
|
|
||||||
final Object[] values = {
|
|
||||||
Keyboard.printableCode(code), withSliding, keyboardState.toString()
|
|
||||||
};
|
|
||||||
getInstance().writeEvent(EVENTKEYS_KEYBOARDSTATE_ONRELEASEKEY, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = {
|
private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = {
|
||||||
"LATINIME_COMMITCURRENTAUTOCORRECTION", "typedWord", "autoCorrection"
|
"LATINIME_COMMITCURRENTAUTOCORRECTION", "typedWord", "autoCorrection"
|
||||||
};
|
};
|
||||||
|
@ -529,7 +493,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = {
|
private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = {
|
||||||
"LATINIME_ONSTARTINPUTVIEWINTERNAL", "uuid", "packageName", "inputType", "imeOptions",
|
"LATINIME_ONSTARTINPUTVIEWINTERNAL", "uuid", "packageName", "inputType", "imeOptions",
|
||||||
"display", "model", "prefs"
|
"fieldId", "display", "model", "prefs"
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
|
public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
|
||||||
|
@ -537,7 +501,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
if (editorInfo != null) {
|
if (editorInfo != null) {
|
||||||
final Object[] values = {
|
final Object[] values = {
|
||||||
getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
|
getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
|
||||||
Integer.toHexString(editorInfo.imeOptions), Build.DISPLAY, Build.MODEL, prefs
|
Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId, Build.DISPLAY,
|
||||||
|
Build.MODEL, prefs
|
||||||
};
|
};
|
||||||
getInstance().writeEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values);
|
getInstance().writeEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values);
|
||||||
}
|
}
|
||||||
|
@ -666,14 +631,33 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = {
|
private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = {
|
||||||
"LATINKEYBOARDVIEW_SETKEYBOARD", "id", "tw", "th", "keys"
|
"LATINKEYBOARDVIEW_SETKEYBOARD", "elementId", "locale", "orientation", "width",
|
||||||
|
"modeName", "action", "navigateNext", "navigatePrevious", "clobberSettingsKey",
|
||||||
|
"passwordInput", "shortcutKeyEnabled", "hasShortcutKey", "languageSwitchKeyEnabled",
|
||||||
|
"isMultiLine", "tw", "th", "keys"
|
||||||
};
|
};
|
||||||
public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) {
|
public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) {
|
||||||
if (keyboard != null) {
|
if (keyboard != null) {
|
||||||
|
final KeyboardId kid = keyboard.mId;
|
||||||
final Object[] values = {
|
final Object[] values = {
|
||||||
keyboard.mId.toString(), keyboard.mOccupiedWidth, keyboard.mOccupiedHeight,
|
KeyboardId.elementIdToName(kid.mElementId),
|
||||||
keyboard
|
kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
|
||||||
};
|
kid.mOrientation,
|
||||||
|
kid.mWidth,
|
||||||
|
KeyboardId.modeName(kid.mMode),
|
||||||
|
kid.imeAction(),
|
||||||
|
kid.navigateNext(),
|
||||||
|
kid.navigatePrevious(),
|
||||||
|
kid.mClobberSettingsKey,
|
||||||
|
kid.passwordInput(),
|
||||||
|
kid.mShortcutKeyEnabled,
|
||||||
|
kid.mHasShortcutKey,
|
||||||
|
kid.mLanguageSwitchKeyEnabled,
|
||||||
|
kid.isMultiLine(),
|
||||||
|
keyboard.mOccupiedWidth,
|
||||||
|
keyboard.mOccupiedHeight,
|
||||||
|
keyboard.mKeys
|
||||||
|
};
|
||||||
getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values);
|
getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,23 +697,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[]
|
|
||||||
EVENTKEYS_POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE = {
|
|
||||||
"POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE", "code",
|
|
||||||
"ignoreModifierKey", "isEnabled"
|
|
||||||
};
|
|
||||||
public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(
|
|
||||||
final Key key, final boolean ignoreModifierKey) {
|
|
||||||
if (key != null) {
|
|
||||||
final Object[] values = {
|
|
||||||
KeyDetector.printableCode(key), ignoreModifierKey, key.isEnabled()
|
|
||||||
};
|
|
||||||
getInstance().writeEvent(
|
|
||||||
EVENTKEYS_POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE,
|
|
||||||
values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = {
|
private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = {
|
||||||
"POINTERTRACKER_CALLLISTENERONRELEASE", "code", "withSliding", "ignoreModifierKey",
|
"POINTERTRACKER_CALLLISTENERONRELEASE", "code", "withSliding", "ignoreModifierKey",
|
||||||
"isEnabled"
|
"isEnabled"
|
||||||
|
@ -785,7 +752,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) {
|
public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) {
|
||||||
if (suggestedWords != null) {
|
if (suggestedWords != null) {
|
||||||
final Object[] values = {
|
final Object[] values = {
|
||||||
suggestedWords.toString()
|
suggestedWords
|
||||||
};
|
};
|
||||||
getInstance().writeEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, values);
|
getInstance().writeEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, values);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue