~singpolyma/cheogram-android

ff84ee6964f16f98dc2691dd77bb4906451dbb11 — Daniel Gultsch 5 years ago ba21c9b
cache channel search results
M build.gradle => build.gradle +1 -0
@@ 66,6 66,7 @@ dependencies {
    implementation "com.leinardi.android:speed-dial:2.0.1"
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
    implementation 'com.google.guava:guava:27.1-android'
    quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.10.1'
}


M proguard-rules.pro => proguard-rules.pro +2 -0
@@ 18,3 18,5 @@
-dontwarn org.bouncycastle.cert.dane.**
-dontwarn rocks.xmpp.addr.**
-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector
-dontwarn java.lang.**
-dontwarn javax.lang.**

M src/main/java/eu/siacs/conversations/http/services/MuclumbusService.java => src/main/java/eu/siacs/conversations/http/services/MuclumbusService.java +17 -4
@@ 1,5 1,7 @@
package eu.siacs.conversations.http.services;

import com.google.common.base.Objects;

import java.util.Collections;
import java.util.List;
import java.util.Set;


@@ 31,12 33,8 @@ public interface MuclumbusService {
    class Room implements AvatarService.Avatarable {

        public String address;
        public int nusers;
        public boolean is_open;
        public String anonymity_mode;
        public String name;
        public String description;
        public String language;

        public String getName() {
            return name;


@@ 59,6 57,21 @@ public interface MuclumbusService {
            Jid room = getRoom();
            return UIHelper.getColorForName(room != null ? room.asBareJid().toEscapedString() : name);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Room room = (Room) o;
            return Objects.equal(address, room.address) &&
                    Objects.equal(name, room.name) &&
                    Objects.equal(description, room.description);
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(address, name, description);
        }
    }

    class SearchRequest {

A src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java => src/main/java/eu/siacs/conversations/services/ChannelDiscoveryService.java +106 -0
@@ 0,0 1,106 @@
package eu.siacs.conversations.services;

import android.util.Log;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.http.services.MuclumbusService;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ChannelDiscoveryService {

    private final XmppConnectionService service;


    private final MuclumbusService muclumbusService;

    private final Cache<String, List<MuclumbusService.Room>> cache;

    public ChannelDiscoveryService(XmppConnectionService service) {
        this.service = service;
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.CHANNEL_DISCOVERY)
                .addConverterFactory(GsonConverterFactory.create())
                .callbackExecutor(Executors.newSingleThreadExecutor())
                .build();
        this.muclumbusService = retrofit.create(MuclumbusService.class);
        this.cache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
    }

    public void discover(String query, OnChannelSearchResultsFound onChannelSearchResultsFound) {
        final boolean all = query == null || query.trim().isEmpty();
        Log.d(Config.LOGTAG, "discover channels. query=" + query);
        List<MuclumbusService.Room> result = cache.getIfPresent(all ? "" : query);
        if (result != null) {
            onChannelSearchResultsFound.onChannelSearchResultsFound(result);
            return;
        }
        if (all) {
            discoverChannels(onChannelSearchResultsFound);
        } else {
            discoverChannels(query, onChannelSearchResultsFound);
        }
    }

    private void discoverChannels(OnChannelSearchResultsFound listener) {
        Call<MuclumbusService.Rooms> call = muclumbusService.getRooms(1);
        try {
            call.enqueue(new Callback<MuclumbusService.Rooms>() {
                @Override
                public void onResponse(Call<MuclumbusService.Rooms> call, Response<MuclumbusService.Rooms> response) {
                    final MuclumbusService.Rooms body = response.body();
                    if (body == null) {
                        return;
                    }
                    cache.put("", body.items);
                    listener.onChannelSearchResultsFound(body.items);
                }

                @Override
                public void onFailure(Call<MuclumbusService.Rooms> call, Throwable throwable) {

                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void discoverChannels(final String query, OnChannelSearchResultsFound listener) {
        Call<MuclumbusService.SearchResult> searchResultCall = muclumbusService.search(new MuclumbusService.SearchRequest(query));

        searchResultCall.enqueue(new Callback<MuclumbusService.SearchResult>() {
            @Override
            public void onResponse(Call<MuclumbusService.SearchResult> call, Response<MuclumbusService.SearchResult> response) {
                System.out.println(response.message());
                MuclumbusService.SearchResult body = response.body();
                if (body == null) {
                    return;
                }
                cache.put(query, body.result.items);
                listener.onChannelSearchResultsFound(body.result.items);
            }

            @Override
            public void onFailure(Call<MuclumbusService.SearchResult> call, Throwable throwable) {
                throwable.printStackTrace();
            }
        });
    }

    public interface OnChannelSearchResultsFound {
        void onChannelSearchResultsFound(List<MuclumbusService.Room> results);
    }
}

M src/main/java/eu/siacs/conversations/services/XmppConnectionService.java => src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +3 -63
@@ 209,6 209,7 @@ public class XmppConnectionService extends Service {
    private FileBackend fileBackend = new FileBackend(this);
    private MemorizingTrustManager mMemorizingTrustManager;
    private NotificationService mNotificationService = new NotificationService(this);
    private ChannelDiscoveryService mChannelDiscoveryService = new ChannelDiscoveryService(this);
    private ShortcutService mShortcutService = new ShortcutService(this);
    private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false);
    private AtomicBoolean mForceForegroundService = new AtomicBoolean(false);


@@ 242,7 243,6 @@ public class XmppConnectionService extends Service {
    private AvatarService mAvatarService = new AvatarService(this);
    private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
    private PushManagementService mPushManagementService = new PushManagementService(this);
    private MuclumbusService muclumbusService;
    private QuickConversationsService mQuickConversationsService = new QuickConversationsService(this);
    private final ConversationsFileObserver fileObserver = new ConversationsFileObserver(
            Environment.getExternalStorageDirectory().getAbsolutePath()


@@ 805,61 805,8 @@ public class XmppConnectionService extends Service {
        return pingNow;
    }

    public void discoverChannels(String query, OnChannelSearchResultsFound onChannelSearchResultsFound) {
        Log.d(Config.LOGTAG,"discover channels. query="+query);
        if (query == null || query.trim().isEmpty()) {
            discoverChannelsInternal(onChannelSearchResultsFound);
        } else {
            discoverChannelsInternal(query, onChannelSearchResultsFound);
        }
    }

    private void discoverChannelsInternal(OnChannelSearchResultsFound listener) {
        Call<MuclumbusService.Rooms> call = muclumbusService.getRooms(1);
        try {
            call.enqueue(new Callback<MuclumbusService.Rooms>() {
                @Override
                public void onResponse(Call<MuclumbusService.Rooms> call, Response<MuclumbusService.Rooms> response) {
                    final MuclumbusService.Rooms body = response.body();
                    if (body == null) {
                        return;
                    }
                    listener.onChannelSearchResultsFound(body.items);
                }

                @Override
                public void onFailure(Call<MuclumbusService.Rooms> call, Throwable throwable) {

                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void discoverChannelsInternal(String query, OnChannelSearchResultsFound listener) {
        Call<MuclumbusService.SearchResult> searchResultCall = muclumbusService.search(new MuclumbusService.SearchRequest(query));

        searchResultCall.enqueue(new Callback<MuclumbusService.SearchResult>() {
            @Override
            public void onResponse(Call<MuclumbusService.SearchResult> call, Response<MuclumbusService.SearchResult> response) {
                System.out.println(response.message());
                MuclumbusService.SearchResult body = response.body();
                if (body == null) {
                    return;
                }
                listener.onChannelSearchResultsFound(body.result.items);
            }

            @Override
            public void onFailure(Call<MuclumbusService.SearchResult> call, Throwable throwable) {
                throwable.printStackTrace();
            }
        });
    }

    public interface OnChannelSearchResultsFound {
        void onChannelSearchResultsFound(List<MuclumbusService.Room> results);
    public void discoverChannels(String query, ChannelDiscoveryService.OnChannelSearchResultsFound onChannelSearchResultsFound) {
        mChannelDiscoveryService.discover(query, onChannelSearchResultsFound);
    }

    public boolean isDataSaverDisabled() {


@@ 1130,13 1077,6 @@ public class XmppConnectionService extends Service {
        }
        mForceDuringOnCreate.set(false);
        toggleForegroundService();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.CHANNEL_DISCOVERY)
                .addConverterFactory(GsonConverterFactory.create())
                .callbackExecutor(Executors.newSingleThreadExecutor())
                .build();
        muclumbusService = retrofit.create(MuclumbusService.class);
    }

    private void checkForDeletedFiles() {

M src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java => src/main/java/eu/siacs/conversations/ui/ChannelDiscoveryActivity.java +17 -7
@@ 2,7 2,6 @@ package eu.siacs.conversations.ui;

import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.databinding.DataBindingUtil;
import android.os.Bundle;


@@ 25,19 24,21 @@ import eu.siacs.conversations.databinding.ActivityChannelDiscoveryBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.http.services.MuclumbusService;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.services.ChannelDiscoveryService;
import eu.siacs.conversations.ui.adapter.ChannelSearchResultAdapter;
import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
import eu.siacs.conversations.utils.AccountUtils;
import rocks.xmpp.addr.Jid;

public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.OnActionExpandListener, TextView.OnEditorActionListener, XmppConnectionService.OnChannelSearchResultsFound, ChannelSearchResultAdapter.OnChannelSearchResultSelected {
public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.OnActionExpandListener, TextView.OnEditorActionListener, ChannelDiscoveryService.OnChannelSearchResultsFound, ChannelSearchResultAdapter.OnChannelSearchResultSelected {

    private static final String CHANNEL_DISCOVERY_OPT_IN = "channel_discovery_opt_in";

    private final ChannelSearchResultAdapter adapter = new ChannelSearchResultAdapter();

    private ActivityChannelDiscoveryBinding binding;

    private final PendingItem<String> mInitialSearchValue = new PendingItem<>();

    private MenuItem mMenuSearchView;


@@ 66,7 67,7 @@ public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.O
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityChannelDiscoveryBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_channel_discovery);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_channel_discovery);
        setSupportActionBar((Toolbar) binding.toolbar);
        configureActionBar(getSupportActionBar(), true);
        binding.list.setAdapter(this.adapter);


@@ 116,13 117,18 @@ public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.O
        final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
        mSearchEditText.setText("");
        adapter.submitList(Collections.emptyList());
        toggleLoadingScreen();
        if (optedIn) {
            xmppConnectionService.discoverChannels(null, this);
        }
        return true;
    }

    private void toggleLoadingScreen() {
        adapter.submitList(Collections.emptyList());
        binding.progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void onStart() {
        super.onStart();


@@ 159,14 165,18 @@ public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.O
        if (optedIn) {
            xmppConnectionService.discoverChannels(v.getText().toString(), this);
        }
        adapter.submitList(Collections.emptyList());
        toggleLoadingScreen();
        SoftKeyboardUtils.hideSoftKeyboard(this);
        return true;
    }

    @Override
    public void onChannelSearchResultsFound(List<MuclumbusService.Room> results) {
        runOnUiThread(() -> adapter.submitList(results));
        runOnUiThread(() -> {
            adapter.submitList(results);
            binding.list.setVisibility(View.VISIBLE);
            binding.progressBar.setVisibility(View.GONE);
        });

    }


M src/main/java/eu/siacs/conversations/ui/adapter/ChannelSearchResultAdapter.java => src/main/java/eu/siacs/conversations/ui/adapter/ChannelSearchResultAdapter.java +1 -1
@@ 22,7 22,7 @@ public class ChannelSearchResultAdapter extends ListAdapter<MuclumbusService.Roo
    private static final DiffUtil.ItemCallback<MuclumbusService.Room> DIFF = new DiffUtil.ItemCallback<MuclumbusService.Room>() {
        @Override
        public boolean areItemsTheSame(@NonNull MuclumbusService.Room a, @NonNull MuclumbusService.Room b) {
            return false;
            return a.address != null && a.address.equals(b.address);
        }

        @Override

M src/main/java/eu/siacs/conversations/ui/adapter/MediaPreviewAdapter.java => src/main/java/eu/siacs/conversations/ui/adapter/MediaPreviewAdapter.java +0 -4
@@ 1,6 1,5 @@
package eu.siacs.conversations.ui.adapter;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.databinding.DataBindingUtil;


@@ 8,7 7,6 @@ import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;


@@ 17,7 15,6 @@ import android.widget.ImageView;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;



@@ 26,7 23,6 @@ import eu.siacs.conversations.databinding.MediaPreviewBinding;
import eu.siacs.conversations.ui.ConversationFragment;
import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.util.Attachment;
import eu.siacs.conversations.ui.util.StyledAttributes;

public class MediaPreviewAdapter extends RecyclerView.Adapter<MediaPreviewAdapter.MediaPreviewViewHolder> {


M src/main/res/layout/activity_channel_discovery.xml => src/main/res/layout/activity_channel_discovery.xml +9 -1
@@ 14,18 14,26 @@
            layout="@layout/toolbar" />


        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_anchor="@+id/list"
            android:layout_gravity="center_horizontal"/>

        <android.support.design.widget.CoordinatorLayout
            android:id="@+id/coordinator"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="?attr/color_background_primary">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="?attr/color_background_primary"
                android:orientation="vertical"
                android:visibility="gone"
                app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
        </android.support.design.widget.CoordinatorLayout>