mirror of
https://github.com/leanote/leanote-android.git
synced 2025-10-15 14:51:04 +00:00
temporary commit about support tag
This commit is contained in:
@@ -3,6 +3,8 @@ package org.houxg.leamonax.database;
|
||||
import android.util.Log;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Database;
|
||||
import com.raizlabs.android.dbflow.sql.language.Join;
|
||||
import com.raizlabs.android.dbflow.sql.language.NameAlias;
|
||||
import com.raizlabs.android.dbflow.sql.language.SQLite;
|
||||
|
||||
import org.houxg.leamonax.model.Account;
|
||||
@@ -13,11 +15,16 @@ import org.houxg.leamonax.model.NoteFile_Table;
|
||||
import org.houxg.leamonax.model.Note_Table;
|
||||
import org.houxg.leamonax.model.Notebook;
|
||||
import org.houxg.leamonax.model.Notebook_Table;
|
||||
import org.houxg.leamonax.model.RelationshipOfNoteTag;
|
||||
import org.houxg.leamonax.model.RelationshipOfNoteTag_Table;
|
||||
import org.houxg.leamonax.model.Tag;
|
||||
import org.houxg.leamonax.model.Tag_Table;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
//TODO:upgrade to Ver.2, handle tags
|
||||
@Database(name = "leanote_db", version = 1)
|
||||
public class AppDataBase {
|
||||
|
||||
@@ -206,4 +213,21 @@ public class AppDataBase {
|
||||
.where(Account_Table.token.notEq(""))
|
||||
.querySingle();
|
||||
}
|
||||
|
||||
public static List<Tag> getTagByNoteLocalId(long noteLocalId) {
|
||||
return SQLite.select()
|
||||
.from(Tag.class).as("T")
|
||||
.join(RelationshipOfNoteTag.class, Join.JoinType.INNER).as("R")
|
||||
.on(Tag_Table.id.withTable(NameAlias.builder("T").build())
|
||||
.eq(RelationshipOfNoteTag_Table.tagLocalId.withTable(NameAlias.builder("R").build())))
|
||||
.where(RelationshipOfNoteTag_Table.noteLocalId.withTable(NameAlias.builder("R").build()).eq(noteLocalId))
|
||||
.queryList();
|
||||
}
|
||||
|
||||
public static Tag getTagByText(String text) {
|
||||
return SQLite.select()
|
||||
.from(Tag.class)
|
||||
.where(Tag_Table.text.eq(text))
|
||||
.querySingle();
|
||||
}
|
||||
}
|
||||
|
@@ -196,6 +196,10 @@ public class Note extends BaseModel implements Serializable {
|
||||
this.noteId = noteId;
|
||||
}
|
||||
|
||||
public List<String> getTagData() {
|
||||
return tagData;
|
||||
}
|
||||
|
||||
public void updateTags() {
|
||||
if (CollectionUtils.isEmpty(tagData)) {
|
||||
tags = "";
|
||||
|
@@ -0,0 +1,28 @@
|
||||
package org.houxg.leamonax.model;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Column;
|
||||
import com.raizlabs.android.dbflow.annotation.QueryModel;
|
||||
import com.raizlabs.android.dbflow.structure.BaseQueryModel;
|
||||
|
||||
import org.houxg.leamonax.database.AppDataBase;
|
||||
|
||||
@QueryModel(database = AppDataBase.class)
|
||||
public class QueryTagRelationship extends BaseQueryModel{
|
||||
|
||||
@Column(name = "tagId")
|
||||
String tagId;
|
||||
@Column(name = "userId")
|
||||
String UserId;
|
||||
@Column(name = "text")
|
||||
String text;
|
||||
@Column(name = "isDeleted")
|
||||
boolean isDeleted;
|
||||
@Column(name = "usn")
|
||||
int usn;
|
||||
@Column(name = "id")
|
||||
long id;
|
||||
@Column(name = "createdTime")
|
||||
long createdTime;
|
||||
@Column(name = "updatedTime")
|
||||
long updatedTime;
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package org.houxg.leamonax.model;
|
||||
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Column;
|
||||
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
|
||||
import com.raizlabs.android.dbflow.annotation.Table;
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
|
||||
import org.houxg.leamonax.database.AppDataBase;
|
||||
|
||||
@Table(name = "RelationshipOfNoteTag", database = AppDataBase.class)
|
||||
public class RelationshipOfNoteTag extends BaseModel {
|
||||
@Column(name = "id")
|
||||
@PrimaryKey(autoincrement = true)
|
||||
long id;
|
||||
|
||||
@Column(name = "noteLocalId")
|
||||
long noteLocalId;
|
||||
|
||||
@Column(name = "tagLocalId")
|
||||
long tagLocalId;
|
||||
|
||||
@Column(name = "userId")
|
||||
String userId;
|
||||
|
||||
RelationshipOfNoteTag() {
|
||||
}
|
||||
|
||||
public RelationshipOfNoteTag(long noteLocalId, long tagLocalId, String userId) {
|
||||
this.noteLocalId = noteLocalId;
|
||||
this.tagLocalId = tagLocalId;
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
119
app/src/main/java/org/houxg/leamonax/model/Tag.java
Normal file
119
app/src/main/java/org/houxg/leamonax/model/Tag.java
Normal file
@@ -0,0 +1,119 @@
|
||||
package org.houxg.leamonax.model;
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.raizlabs.android.dbflow.annotation.Column;
|
||||
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
|
||||
import com.raizlabs.android.dbflow.annotation.Table;
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
|
||||
import org.houxg.leamonax.database.AppDataBase;
|
||||
import org.houxg.leamonax.utils.TimeUtils;
|
||||
|
||||
@Table(name = "Tag", database = AppDataBase.class)
|
||||
public class Tag extends BaseModel{
|
||||
|
||||
@SerializedName("TagId")
|
||||
@Column(name = "tagId")
|
||||
String tagId;
|
||||
@SerializedName("UserId")
|
||||
@Column(name = "userId")
|
||||
String UserId;
|
||||
@SerializedName("Tag")
|
||||
@Column(name = "text")
|
||||
String text;
|
||||
@SerializedName("IsDeleted")
|
||||
@Column(name = "isDeleted")
|
||||
boolean isDeleted;
|
||||
@SerializedName("Usn")
|
||||
@Column(name = "usn")
|
||||
int usn;
|
||||
@SerializedName("CreatedTime")
|
||||
String createTimeData;
|
||||
@SerializedName("UpdatedTime")
|
||||
String updatedTimeData;
|
||||
|
||||
@Column(name = "id")
|
||||
@PrimaryKey(autoincrement = true)
|
||||
long id;
|
||||
@Column(name = "createdTime")
|
||||
long createdTime;
|
||||
@Column(name = "updatedTime")
|
||||
long updatedTime;
|
||||
|
||||
Tag() {}
|
||||
|
||||
public Tag(String userId, String text) {
|
||||
UserId = userId;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getTagId() {
|
||||
return tagId;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return UserId;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return isDeleted;
|
||||
}
|
||||
|
||||
public int getUsn() {
|
||||
return usn;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getCreatedTime() {
|
||||
return createdTime;
|
||||
}
|
||||
|
||||
public long getUpdatedTime() {
|
||||
return updatedTime;
|
||||
}
|
||||
|
||||
public void setTagId(String tagId) {
|
||||
this.tagId = tagId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
UserId = userId;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void setDeleted(boolean deleted) {
|
||||
isDeleted = deleted;
|
||||
}
|
||||
|
||||
public void setUsn(int usn) {
|
||||
this.usn = usn;
|
||||
}
|
||||
|
||||
public void setCreatedTime(long createdTime) {
|
||||
this.createdTime = createdTime;
|
||||
}
|
||||
|
||||
public void setUpdatedTime(long updatedTime) {
|
||||
this.updatedTime = updatedTime;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void updateTime() {
|
||||
createdTime = TimeUtils.toTimestamp(createTimeData);
|
||||
updatedTime = TimeUtils.toTimestamp(updatedTimeData);
|
||||
}
|
||||
}
|
@@ -16,6 +16,10 @@ import org.houxg.leamonax.model.Note;
|
||||
import org.houxg.leamonax.model.NoteFile;
|
||||
import org.houxg.leamonax.model.Note_Table;
|
||||
import org.houxg.leamonax.model.Notebook;
|
||||
import org.houxg.leamonax.model.RelationshipOfNoteTag;
|
||||
import org.houxg.leamonax.model.RelationshipOfNoteTag_Table;
|
||||
import org.houxg.leamonax.model.Tag;
|
||||
import org.houxg.leamonax.model.Tag_Table;
|
||||
import org.houxg.leamonax.model.UpdateRe;
|
||||
import org.houxg.leamonax.network.ApiProvider;
|
||||
import org.houxg.leamonax.utils.CollectionUtils;
|
||||
@@ -83,6 +87,7 @@ public class NoteService {
|
||||
Log.i(TAG, "content=" + remoteNote.getContent());
|
||||
remoteNote.update();
|
||||
handleFile(localId, remoteNote.getNoteFiles());
|
||||
handleTag(localId, remoteNote.getTagData());
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
@@ -156,6 +161,55 @@ public class NoteService {
|
||||
AppDataBase.deleteFileExcept(noteLocalId, excepts);
|
||||
}
|
||||
|
||||
private static void handleTag(long noteLocalId, List<String> tags) {
|
||||
List<Long> tagLocalIds = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(tags)) {
|
||||
String currentUserId = AccountService.getCurrent().getUserId();
|
||||
for (String tag : tags) {
|
||||
if (TextUtils.isEmpty(tag)) {
|
||||
continue;
|
||||
}
|
||||
long tagLocalId;
|
||||
Tag tagModel = SQLite.select()
|
||||
.from(Tag.class)
|
||||
.where(Tag_Table.text.eq(tag))
|
||||
.querySingle();
|
||||
if (tagModel == null) {
|
||||
tagModel = new Tag(currentUserId, tag);
|
||||
tagLocalId = tagModel.insert();
|
||||
} else {
|
||||
tagLocalId = tagModel.getId();
|
||||
}
|
||||
|
||||
RelationshipOfNoteTag relationship = SQLite.select()
|
||||
.from(RelationshipOfNoteTag.class)
|
||||
.where(RelationshipOfNoteTag_Table.noteLocalId.eq(noteLocalId))
|
||||
.and(RelationshipOfNoteTag_Table.tagLocalId.eq(tagLocalId))
|
||||
.querySingle();
|
||||
if (relationship == null) {
|
||||
relationship = new RelationshipOfNoteTag(noteLocalId, tagLocalId, currentUserId);
|
||||
relationship.insert();
|
||||
}
|
||||
tagLocalIds.add(tagLocalId);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(tagLocalIds)) {
|
||||
SQLite.delete()
|
||||
.from(RelationshipOfNoteTag.class)
|
||||
.where(RelationshipOfNoteTag_Table.noteLocalId.eq(noteLocalId))
|
||||
.async()
|
||||
.execute();
|
||||
} else {
|
||||
SQLite.delete()
|
||||
.from(RelationshipOfNoteTag.class)
|
||||
.where(RelationshipOfNoteTag_Table.noteLocalId.eq(noteLocalId))
|
||||
.and(RelationshipOfNoteTag_Table.tagLocalId.notIn(tagLocalIds.get(0), CollectionUtils.toPrimitive(tagLocalIds.subList(1, tagLocalIds.size()))))
|
||||
.async()
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private static String convertToLocalImageLinkForRichText(long noteLocalId, String noteContent) {
|
||||
return StringUtils.replace(noteContent,
|
||||
"<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>",
|
||||
@@ -300,6 +354,7 @@ public class NoteService {
|
||||
serverNote.setContent(convertToLocalImageLinkForRichText(localId, serverNote.getContent()));
|
||||
}
|
||||
handleFile(localId, serverNote.getNoteFiles());
|
||||
handleTag(localId, serverNote.getTagData());
|
||||
serverNote.save();
|
||||
return true;
|
||||
}
|
||||
@@ -309,7 +364,7 @@ public class NoteService {
|
||||
List<MultipartBody.Part> fileBodies = handleFileBodies(note, requestBodyMap);
|
||||
return ApiProvider.getInstance().getNoteApi().add(requestBodyMap, fileBodies);
|
||||
}
|
||||
|
||||
|
||||
private static Call<Note> updateNote(Note original, Note modified) {
|
||||
Map<String, RequestBody> requestBodyMap = generateCommonBodyMap(modified);
|
||||
requestBodyMap.put("NoteId", createPartFromString(original.getNoteId()));
|
||||
@@ -338,6 +393,17 @@ public class NoteService {
|
||||
requestBodyMap.put("IsBlog", createPartFromString(getBooleanString(note.isPublicBlog())));
|
||||
requestBodyMap.put("CreatedTime", createPartFromString(TimeUtils.toServerTime(note.getCreatedTimeVal())));
|
||||
requestBodyMap.put("UpdatedTime", createPartFromString(TimeUtils.toServerTime(note.getUpdatedTimeVal())));
|
||||
|
||||
List<Tag> tags = AppDataBase.getTagByNoteLocalId(note.getId());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(tags)) {
|
||||
int size = tags.size();
|
||||
for (int index = 0; index < size; index++) {
|
||||
Tag tag = tags.get(index);
|
||||
requestBodyMap.put(String.format("Tags[%s]", index), createPartFromString(tag.getText()));
|
||||
}
|
||||
}
|
||||
|
||||
return requestBodyMap;
|
||||
}
|
||||
|
||||
|
@@ -21,9 +21,13 @@ import org.houxg.leamonax.R;
|
||||
import org.houxg.leamonax.model.Account;
|
||||
import org.houxg.leamonax.model.BaseResponse;
|
||||
import org.houxg.leamonax.model.Note;
|
||||
import org.houxg.leamonax.model.RelationshipOfNoteTag;
|
||||
import org.houxg.leamonax.model.Note_Table;
|
||||
import org.houxg.leamonax.model.Notebook;
|
||||
import org.houxg.leamonax.model.Notebook_Table;
|
||||
import org.houxg.leamonax.model.RelationshipOfNoteTag_Table;
|
||||
import org.houxg.leamonax.model.Tag;
|
||||
import org.houxg.leamonax.model.Tag_Table;
|
||||
import org.houxg.leamonax.service.AccountService;
|
||||
import org.houxg.leamonax.utils.ToastUtils;
|
||||
|
||||
@@ -182,13 +186,22 @@ public class SettingsActivity extends BaseActivity {
|
||||
@Override
|
||||
public void call(Subscriber<? super Void> subscriber) {
|
||||
if (!subscriber.isUnsubscribed()) {
|
||||
Account currentUser = AccountService.getCurrent();
|
||||
SQLite.delete()
|
||||
.from(Note.class)
|
||||
.where(Note_Table.userId.eq(AccountService.getCurrent().getUserId()))
|
||||
.where(Note_Table.userId.eq(currentUser.getUserId()))
|
||||
.execute();
|
||||
SQLite.delete()
|
||||
.from(Notebook.class)
|
||||
.where(Notebook_Table.userId.eq(AccountService.getCurrent().getUserId()))
|
||||
.where(Notebook_Table.userId.eq(currentUser.getUserId()))
|
||||
.execute();
|
||||
SQLite.delete()
|
||||
.from(Tag.class)
|
||||
.where(Tag_Table.userId.eq(currentUser.getUserId()))
|
||||
.execute();
|
||||
SQLite.delete()
|
||||
.from(RelationshipOfNoteTag.class)
|
||||
.where(RelationshipOfNoteTag_Table.userId.eq(currentUser.getUserId()))
|
||||
.execute();
|
||||
Account account = AccountService.getCurrent();
|
||||
account.setLastUsn(0);
|
||||
|
@@ -17,6 +17,8 @@ import android.view.ViewGroup;
|
||||
import org.houxg.leamonax.R;
|
||||
import org.houxg.leamonax.database.AppDataBase;
|
||||
import org.houxg.leamonax.model.Note;
|
||||
import org.houxg.leamonax.model.Tag;
|
||||
import org.houxg.leamonax.service.AccountService;
|
||||
import org.houxg.leamonax.service.NoteFileService;
|
||||
import org.houxg.leamonax.service.NoteService;
|
||||
import org.houxg.leamonax.ui.BaseActivity;
|
||||
@@ -24,6 +26,9 @@ import org.houxg.leamonax.utils.NetworkUtils;
|
||||
import org.houxg.leamonax.utils.ToastUtils;
|
||||
import org.houxg.leamonax.widget.LeaViewPager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import rx.Observable;
|
||||
import rx.Subscriber;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
@@ -44,6 +49,8 @@ public class NoteEditActivity extends BaseActivity implements EditorFragment.Edi
|
||||
|
||||
private EditorFragment mEditorFragment;
|
||||
private SettingFragment mSettingsFragment;
|
||||
private List<Tag> mOriginalTags;
|
||||
private List<Tag> mModifiedTags;
|
||||
private Note mOriginal;
|
||||
private Note mModified;
|
||||
private boolean mIsNewNote;
|
||||
@@ -73,6 +80,8 @@ public class NoteEditActivity extends BaseActivity implements EditorFragment.Edi
|
||||
mIsNewNote = getIntent().getBooleanExtra(EXT_IS_NEW_NOTE, false);
|
||||
mOriginal = AppDataBase.getNoteByLocalId(noteLocalId);
|
||||
mModified = AppDataBase.getNoteByLocalId(noteLocalId);
|
||||
mOriginalTags = AppDataBase.getTagByNoteLocalId(noteLocalId);
|
||||
mModifiedTags = AppDataBase.getTagByNoteLocalId(noteLocalId);
|
||||
setResult(RESULT_CANCELED);
|
||||
}
|
||||
|
||||
@@ -86,6 +95,7 @@ public class NoteEditActivity extends BaseActivity implements EditorFragment.Edi
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
//TODO:save note state
|
||||
outState.putLong(EXT_NOTE_LOCAL_ID, mModified.getId());
|
||||
outState.putString(TAG_EDITOR, mEditorFragment.getTag());
|
||||
outState.putString(TAG_SETTING, mSettingsFragment.getTag());
|
||||
@@ -199,7 +209,17 @@ public class NoteEditActivity extends BaseActivity implements EditorFragment.Edi
|
||||
mModified.setTitle(title);
|
||||
mModified.setContent(content);
|
||||
mModified.setNoteBookId(mSettingsFragment.getNotebookId());
|
||||
mModified.setTags(mSettingsFragment.getTags());
|
||||
List<String> tagTexts = mSettingsFragment.getTags();
|
||||
mModifiedTags = new ArrayList<>();
|
||||
for (String tagText : tagTexts) {
|
||||
Tag tag = AppDataBase.getTagByText(tagText);
|
||||
if (tag == null) {
|
||||
tag = new Tag(AccountService.getCurrent().getUserId(), tagText);
|
||||
long id = tag.insert();
|
||||
tag.setId(id);
|
||||
}
|
||||
mModifiedTags.add(tag);
|
||||
}
|
||||
mModified.setIsPublicBlog(mSettingsFragment.shouldPublic());
|
||||
}
|
||||
|
||||
@@ -240,7 +260,11 @@ public class NoteEditActivity extends BaseActivity implements EditorFragment.Edi
|
||||
public void onFragmentInitialized() {
|
||||
mSettingsFragment.setNotebookId(mModified.getNoteBookId());
|
||||
mSettingsFragment.setShouldPublic(mModified.isPublicBlog());
|
||||
mSettingsFragment.setTags(mModified.getTags());
|
||||
List<String> tagTexts = new ArrayList<>();
|
||||
for (Tag tag : mModifiedTags) {
|
||||
tagTexts.add(tag.getText());
|
||||
}
|
||||
mSettingsFragment.setTags(tagTexts);
|
||||
}
|
||||
|
||||
private class SectionAdapter extends FragmentPagerAdapter {
|
||||
|
@@ -19,7 +19,10 @@ import org.houxg.leamonax.R;
|
||||
import org.houxg.leamonax.database.AppDataBase;
|
||||
import org.houxg.leamonax.model.Notebook;
|
||||
import org.houxg.leamonax.service.AccountService;
|
||||
import org.houxg.leamonax.utils.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
@@ -65,7 +68,21 @@ public class SettingFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
public void setTags(String tags) {
|
||||
//TODO:input List<Tag>
|
||||
public void setTags(List<String> tagData) {
|
||||
String tags = "";
|
||||
if (CollectionUtils.isNotEmpty(tagData)) {
|
||||
StringBuilder tagBuilder = new StringBuilder();
|
||||
int size = tagData.size();
|
||||
int lastIndex = size - 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
tagBuilder.append(tagData.get(i));
|
||||
if (i < lastIndex) {
|
||||
tagBuilder.append(",");
|
||||
}
|
||||
}
|
||||
tags = tagBuilder.toString();
|
||||
}
|
||||
mTagEt.setText(tags);
|
||||
}
|
||||
|
||||
@@ -91,8 +108,14 @@ public class SettingFragment extends Fragment {
|
||||
return mPublicSw.isChecked();
|
||||
}
|
||||
|
||||
public String getTags() {
|
||||
return mTagEt.getText().toString();
|
||||
//TODO:output List<Tag>
|
||||
public List<String> getTags() {
|
||||
String text = mTagEt.getText().toString();
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return Arrays.asList(text.split(","));
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.ll_notebook)
|
||||
|
@@ -12,4 +12,18 @@ public class CollectionUtils {
|
||||
public static boolean isNotEmpty(Collection collection) {
|
||||
return collection != null && collection.size() > 0;
|
||||
}
|
||||
|
||||
public static long[] toPrimitive(Collection<Long> collection) {
|
||||
if (isEmpty(collection)) {
|
||||
return new long[0];
|
||||
}
|
||||
|
||||
long[] array = new long[collection.size()];
|
||||
int i = 0;
|
||||
for (Long val : collection) {
|
||||
array[i] = val;
|
||||
i++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user