Skip to content

Commit

Permalink
Add to favorites after processing posting response, improve user post…
Browse files Browse the repository at this point in the history
… detection
  • Loading branch information
Mishiranu committed Dec 16, 2020
1 parent 87012c4 commit 8deeb6b
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 71 deletions.
37 changes: 14 additions & 23 deletions src/com/mishiranu/dashchan/content/async/ReadPostsTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
Expand Down Expand Up @@ -112,19 +111,17 @@ protected Result run(HttpHolder holder) {
boolean temporary = chan.configuration.getOption(ChanConfiguration.OPTION_LOCAL_MODE);
PagesDatabase.ThreadKey threadKey = new PagesDatabase.ThreadKey(chan.name, boardName, threadNumber);
PagesDatabase.Meta meta = PagesDatabase.getInstance().getMeta(threadKey, temporary);
PostNumber lastExistingPostNumber = PagesDatabase.getInstance().getLastExistingPostNumber(threadKey);
UpdateMeta updateMeta = null;
PostNumber originalPostNumber;
PostNumber lastExistingPostNumber;
boolean allowPartialThreadLoading;
if (loadFullThread) {
originalPostNumber = null;
lastExistingPostNumber = null;
allowPartialThreadLoading = false;
} else {
PagesDatabase.ThreadSummary threadSummary = PagesDatabase.getInstance().getThreadSummary(threadKey);
originalPostNumber = threadSummary.originalPostNumber;
lastExistingPostNumber = threadSummary.lastExistingPostNumber;
allowPartialThreadLoading = !threadSummary.cyclical ||
Post originalPost = PagesDatabase.getInstance().getOriginalPost(threadKey);
originalPostNumber = originalPost != null ? originalPost.number : null;
allowPartialThreadLoading = originalPost == null || !originalPost.isCyclical() ||
Preferences.getCyclicalRefreshMode() == Preferences.CyclicalRefreshMode.DEFAULT;
}
boolean partial = !loadFullThread && allowPartialThreadLoading && Preferences.isPartialThreadLoading(chan);
Expand Down Expand Up @@ -198,23 +195,17 @@ protected Result run(HttpHolder holder) {
HashSet<PendingUserPost> pendingUserPosts = this.pendingUserPosts;
HashSet<PendingUserPost> removedPendingUserPosts = null;
if (pendingUserPosts != null && !pendingUserPosts.isEmpty()) {
for (Post post : posts) {
if (pendingUserPosts.isEmpty()) {
break;
}
Iterator<PendingUserPost> iterator = pendingUserPosts.iterator();
while (iterator.hasNext()) {
PendingUserPost pendingUserPost = iterator.next();
if (pendingUserPost.isUserPost(post, post.number.equals(originalPostNumber))) {
iterator.remove();
if (removedPendingUserPosts == null) {
removedPendingUserPosts = new HashSet<>();
}
removedPendingUserPosts.add(pendingUserPost);
CommonDatabase.getInstance().getPosts().setFlags(false, chan.name,
boardName, threadNumber, post.number, PostItem.HideState.UNDEFINED, true);
break;
boolean firstPostIsOriginal = posts.get(0).number.equals(originalPostNumber);
for (PendingUserPost pendingUserPost : pendingUserPosts) {
PostNumber postNumber = pendingUserPost.findUserPost(posts,
lastExistingPostNumber, firstPostIsOriginal);
if (postNumber != null) {
if (removedPendingUserPosts == null) {
removedPendingUserPosts = new HashSet<>();
}
removedPendingUserPosts.add(pendingUserPost);
CommonDatabase.getInstance().getPosts().setFlags(false, chan.name,
boardName, threadNumber, postNumber, PostItem.HideState.UNDEFINED, true);
}
}
}
Expand Down
61 changes: 28 additions & 33 deletions src/com/mishiranu/dashchan/content/database/PagesDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,6 @@ public static Meta deserialize(JsonSerial.Reader reader,
}
}

public static class ThreadSummary {
public final PostNumber originalPostNumber;
public final PostNumber lastExistingPostNumber;
public final boolean cyclical;

public ThreadSummary(PostNumber originalPostNumber, PostNumber lastExistingPostNumber, boolean cyclical) {
this.originalPostNumber = originalPostNumber;
this.lastExistingPostNumber = lastExistingPostNumber;
this.cyclical = cyclical;
}
}

public static class WatcherState {
public final int newCount;
public final boolean deleted;
Expand Down Expand Up @@ -612,53 +600,58 @@ public void setMetaFlags(@NonNull ThreadKey threadKey, boolean deleted, boolean
"WHERE " + filter.value, filter.args);
}

public ThreadSummary getThreadSummary(@NonNull ThreadKey threadKey) {
private static String orderByPostNumber(boolean desc) {
String order = (desc ? "DESC" : "ASC");
return Schema.Posts.Columns.POST_NUMBER_MAJOR + " " + order + ", " +
Schema.Posts.Columns.POST_NUMBER_MINOR + " " + order;
}

public PostNumber getLastExistingPostNumber(@NonNull ThreadKey threadKey) {
Objects.requireNonNull(threadKey);
String[] lastPostProjection = {Schema.Posts.Columns.POST_NUMBER_MAJOR, Schema.Posts.Columns.POST_NUMBER_MINOR};
Expression.Filter lastPostFilter = threadKey.filterPosts()
String[] projection = {Schema.Posts.Columns.POST_NUMBER_MAJOR, Schema.Posts.Columns.POST_NUMBER_MINOR};
Expression.Filter filter = threadKey.filterPosts()
.raw("NOT (" + Schema.Posts.Columns.FLAGS + " & " + Schema.Posts.Flags.DELETED + ")")
.build();
PostNumber lastExistingPostNumber;
try (Cursor cursor = database.query(Schema.Posts.TABLE_NAME, lastPostProjection, lastPostFilter.value,
lastPostFilter.args, null, null, Schema.Posts.Columns.POST_NUMBER_MAJOR + " DESC, " +
Schema.Posts.Columns.POST_NUMBER_MINOR + " DESC", "1")) {
lastExistingPostNumber = cursor.moveToFirst() ? new PostNumber(cursor.getInt(0), cursor.getInt(1)) : null;
try (Cursor cursor = database.query(Schema.Posts.TABLE_NAME, projection, filter.value,
filter.args, null, null, orderByPostNumber(true), "1")) {
return cursor.moveToFirst() ? new PostNumber(cursor.getInt(0), cursor.getInt(1)) : null;
}
String[] originalPostProjection = {Schema.Posts.Columns.POST_NUMBER_MAJOR,
}

public Post getOriginalPost(@NonNull ThreadKey threadKey) {
Objects.requireNonNull(threadKey);
String[] projection = {Schema.Posts.Columns.POST_NUMBER_MAJOR,
Schema.Posts.Columns.POST_NUMBER_MINOR, Schema.Posts.Columns.DATA};
Expression.Filter originalPostFilter = threadKey.filterPosts().build();
PostNumber originalPostNumber = null;
boolean cyclical = false;
try (Cursor cursor = database.query(Schema.Posts.TABLE_NAME, originalPostProjection, originalPostFilter.value,
originalPostFilter.args, null, null, Schema.Posts.Columns.POST_NUMBER_MAJOR + " ASC, " +
Schema.Posts.Columns.POST_NUMBER_MINOR + " ASC", "1")) {
Expression.Filter filter = threadKey.filterPosts().build();
try (Cursor cursor = database.query(Schema.Posts.TABLE_NAME, projection,
filter.value, filter.args, null, null, orderByPostNumber(false), "1")) {
if (cursor.moveToFirst()) {
originalPostNumber = new PostNumber(cursor.getInt(0), cursor.getInt(1));
PostNumber postNumber = new PostNumber(cursor.getInt(0), cursor.getInt(1));
try (JsonSerial.Reader reader = JsonSerial.reader(cursor.getBlob(2))) {
cyclical = Post.deserialize(originalPostNumber, false, reader).isCyclical();
return Post.deserialize(postNumber, false, reader);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
// Ignore
}
}
}
return new ThreadSummary(originalPostNumber, lastExistingPostNumber, cyclical);
return null;
}

public List<PostNumber> getPostNumbers(@NonNull ThreadKey threadKey) {
Objects.requireNonNull(threadKey);
String[] projection = {Schema.Posts.Columns.POST_NUMBER_MAJOR, Schema.Posts.Columns.POST_NUMBER_MINOR};
Expression.Filter filter = threadKey.filterPosts().build();
ArrayList<PostNumber> postNumbers;
try (Cursor cursor = database.query(Schema.Posts.TABLE_NAME, projection, filter.value, filter.args, null, null,
Schema.Posts.Columns.POST_NUMBER_MAJOR + " ASC, " + Schema.Posts.Columns.POST_NUMBER_MINOR + " ASC")) {
try (Cursor cursor = database.query(Schema.Posts.TABLE_NAME, projection,
filter.value, filter.args, null, null, orderByPostNumber(false))) {
postNumbers = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
postNumbers.add(new PostNumber(cursor.getInt(0), cursor.getInt(1)));
}
}
return postNumbers != null ? postNumbers : Collections.emptyList();
return postNumbers;
}

public WatcherState getWatcherState(@NonNull ThreadKey threadKey) {
Expand Down Expand Up @@ -715,6 +708,8 @@ private void upsertMeta(ThreadKey threadKey, long time, Meta meta) throws IOExce
Expression.Filter filter = threadKey.filterMeta().build();
ContentValues values = new ContentValues();
values.put(Schema.Meta.Columns.TIME, time);
int flags = (meta.deleted ? Schema.Meta.Flags.DELETED : 0) | (meta.error ? Schema.Meta.Flags.ERROR : 0);
values.put(Schema.Meta.Columns.FLAGS, flags);
try (JsonSerial.Writer writer = JsonSerial.writer()) {
meta.serialize(writer);
values.put(Schema.Meta.Columns.DATA, writer.build());
Expand Down
39 changes: 31 additions & 8 deletions src/com/mishiranu/dashchan/content/model/PendingUserPost.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@

import com.mishiranu.dashchan.text.HtmlParser;
import com.mishiranu.dashchan.text.SimilarTextEstimator;
import java.util.List;

public interface PendingUserPost {
boolean isUserPost(Post post, boolean originalPost);
PostNumber findUserPost(List<Post> posts, PostNumber lastExistingPostNumber, boolean firstPostIsOriginal);

class NewThread implements PendingUserPost {
public static final NewThread INSTANCE = new NewThread();

private NewThread() {}

@Override
public boolean isUserPost(Post post, boolean originalPost) {
return originalPost;
public PostNumber findUserPost(List<Post> posts,
PostNumber lastExistingPostNumber, boolean firstPostIsOriginal) {
return firstPostIsOriginal && !posts.isEmpty() ? posts.get(0).number : null;
}

@Override
Expand All @@ -31,16 +33,37 @@ class SimilarComment implements PendingUserPost {
private static final SimilarTextEstimator ESTIMATOR = new SimilarTextEstimator(Integer.MAX_VALUE, true);

private final SimilarTextEstimator.WordsData<Void> wordsData;
private final long time;

public SimilarComment(String comment) {
public SimilarComment(String comment, long time) {
wordsData = ESTIMATOR.getWords(comment);
this.time = time;
}

@Override
public boolean isUserPost(Post post, boolean originalPost) {
String comment = HtmlParser.clear(post.comment);
SimilarTextEstimator.WordsData<Void> wordsData = ESTIMATOR.getWords(comment);
return ESTIMATOR.checkSimiliar(this.wordsData, wordsData) || this.wordsData == null && wordsData == null;
public PostNumber findUserPost(List<Post> posts,
PostNumber lastExistingPostNumber, boolean firstPostIsOriginal) {
if (lastExistingPostNumber != null) {
for (int i = 0; i < posts.size(); i++) {
Post post = posts.get(i);
if (post.number.compareTo(lastExistingPostNumber) > 0) {
posts = posts.subList(i, posts.size());
break;
}
}
}
Post foundPost = null;
for (Post post : posts) {
String comment = HtmlParser.clear(post.comment);
SimilarTextEstimator.WordsData<Void> wordsData = ESTIMATOR.getWords(comment);
if (ESTIMATOR.checkSimiliar(this.wordsData, wordsData) ||
this.wordsData == null && wordsData == null) {
if (foundPost == null || Math.abs(foundPost.timestamp - time) > Math.abs(post.timestamp - time)) {
foundPost = post;
}
}
}
return foundPost != null ? foundPost.number : null;
}

@Override
Expand Down
14 changes: 7 additions & 7 deletions src/com/mishiranu/dashchan/content/service/PostingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -435,10 +435,6 @@ public void onSendPostSuccess(Key key, ChanPerformer.SendPostData data,
Chan chan = Chan.get(chanName);
String targetThreadNumber = data.threadNumber != null ? data.threadNumber
: StringUtils.nullIfEmpty(threadNumber);
if (targetThreadNumber != null && Preferences.getFavoriteOnReply().isEnabled(data.optionSage)) {
FavoritesStorage.getInstance().add(chanName, data.boardName, targetThreadNumber, null, true);
}
StatisticsStorage.getInstance().incrementPostsSent(chanName, data.threadNumber == null);
DraftsStorage draftsStorage = DraftsStorage.getInstance();
draftsStorage.removeCaptchaDraft();
draftsStorage.removePostDraft(chanName, data.boardName, data.threadNumber);
Expand Down Expand Up @@ -469,7 +465,7 @@ public void onSendPostSuccess(Key key, ChanPerformer.SendPostData data,
} else if (newThread) {
pendingUserPost = PendingUserPost.NewThread.INSTANCE;
} else {
pendingUserPost = new PendingUserPost.SimilarComment(comment);
pendingUserPost = new PendingUserPost.SimilarComment(comment, System.currentTimeMillis());
}
if (pendingUserPost != null) {
HashSet<PendingUserPost> pendingUserPosts = PENDING_USER_POST_MAP.get(arrayKey);
Expand Down Expand Up @@ -515,6 +511,11 @@ public void onSendPostSuccess(Key key, ChanPerformer.SendPostData data,
notificationManager.notify(tag, 0, builder.build());
}

if (targetThreadNumber != null && Preferences.getFavoriteOnReply().isEnabled(data.optionSage)) {
// Add to favorites after processing the response to ensure watcher is not triggered too early
FavoritesStorage.getInstance().add(chanName, data.boardName, targetThreadNumber, null, true);
}
StatisticsStorage.getInstance().incrementPostsSent(chanName, data.threadNumber == null);
ArrayList<Callback> callbacks = this.callbacks.get(key);
if (callbacks != null) {
for (Callback callback : callbacks) {
Expand Down Expand Up @@ -646,8 +647,7 @@ public static void consumePendingUserPosts(String chanName, String boardName, St

private static final HashMap<Key, ArrayList<NewPostData>> NEW_POST_DATA_MAP = new HashMap<>();

public static boolean consumeNewPostData(Context context, String chanName, String boardName,
String threadNumber) {
public static boolean consumeNewPostData(Context context, String chanName, String boardName, String threadNumber) {
ArrayList<NewPostData> newPostDataList = NEW_POST_DATA_MAP
.remove(new Key(chanName, boardName, threadNumber));
if (newPostDataList != null) {
Expand Down

0 comments on commit 8deeb6b

Please sign in to comment.