diff --git a/app/build.gradle b/app/build.gradle index 7547f70f79ab1e03ac88f604118614f6a286718b..a2fd16b3ee3b9d9b9ae8655e99e11e4a2ebcf080 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -159,6 +159,8 @@ dependencies { compile "com.github.Raizlabs.DBFlow:dbflow-core:3.1.1" compile "com.github.Raizlabs.DBFlow:dbflow:3.1.1" + + // Appcompat compile 'com.android.support:appcompat-v7:24.0.0' compile 'com.android.support:design:24.0.0' compile 'com.android.support:support-v4:24.0.0' @@ -166,6 +168,15 @@ dependencies { compile 'com.android.support:preference-v14:24.0.0' compile 'com.android.support:cardview-v7:24.0.0' + // Reactive Libs + compile 'io.reactivex:rxandroid:1.2.1' + compile 'io.reactivex:rxjava:1.1.6' + compile 'com.jakewharton.rxbinding:rxbinding:0.4.0' + compile 'com.jakewharton.rxbinding:rxbinding-support-v4:0.4.0' + compile 'com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.4.0' + compile 'com.jakewharton.rxbinding:rxbinding-design:0.4.0' + compile 'com.jakewharton.rxbinding:rxbinding-recyclerview-v7:0.4.0' + // Crashreports compile 'ch.acra:acra:4.9.0' diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java b/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java index e251540c845853b61c86b3c9eba08318b756f801..0281af62ebb68ec7e7c03ac51185af8d692b830c 100644 --- a/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java +++ b/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java @@ -36,6 +36,7 @@ import de.kuschku.libquassel.client.Client; import de.kuschku.libquassel.message.Message; import de.kuschku.libquassel.primitives.types.BufferInfo; import de.kuschku.libquassel.syncables.types.interfaces.QNetwork; +import de.kuschku.util.irc.IrcUserUtils; import de.kuschku.util.observables.callbacks.UICallback; import de.kuschku.util.observables.lists.ObservableComparableSortedList; @@ -52,6 +53,8 @@ public class BacklogFilter implements UICallback { @NonNull private final Set<Message.Type> filteredTypes = new HashSet<>(); + @Nullable + private CharSequence searchQuery; private final EventBus bus = new EventBus(); @Nullable private DateTime earliestMessage; @@ -96,7 +99,10 @@ public class BacklogFilter implements UICallback { private boolean filterItem(@NonNull Message message) { QNetwork network = client.networkManager().network(client.bufferManager().buffer(message.bufferInfo.id).getInfo().networkId); assertNotNull(network); - return (client.ignoreListManager() != null && client.ignoreListManager().matches(message, network)) || filteredTypes.contains(message.type); + boolean ignored = client.ignoreListManager() != null && client.ignoreListManager().matches(message, network); + boolean filtered = filteredTypes.contains(message.type); + boolean isSearching = searchQuery != null && searchQuery.length() != 0; + return ignored || filtered || (isSearching && !message.content.contains(searchQuery)); } public void addFilter(Message.Type type) { @@ -114,6 +120,11 @@ public class BacklogFilter implements UICallback { bus.post(new UpdateRemoveEvent()); } + public void setQuery(CharSequence query) { + searchQuery = query; + update(); + } + public void onEventAsync(UpdateAddEvent event) { for (Message message : unfiltered) { if (!filterItem(message)) { diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java index 95ef6c34ea0ec552fc315a5a5b043aeb974da076..1df4329f9112162158fc82540a702cacc7029c61 100644 --- a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java +++ b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java @@ -24,6 +24,8 @@ package de.kuschku.libquassel.localtypes.backlogstorage; import android.support.annotation.IntRange; import android.support.annotation.NonNull; +import java.util.List; + import de.kuschku.libquassel.client.Client; import de.kuschku.libquassel.localtypes.BacklogFilter; import de.kuschku.libquassel.message.Message; @@ -43,8 +45,12 @@ public interface BacklogStorage { void insertMessages(@IntRange(from = 0) int bufferId, Message... messages); + void insertMessages(@IntRange(from = 0) int bufferId, List<Message> messages); + void insertMessages(Message... messages); + void insertMessages(List<Message> messages); + void setClient(Client client); void markBufferUnused(@IntRange(from = 0) int bufferid); diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java index 0127826dacb72994fcfb3703f8778c7fc23d7ac6..f702dcb0db8bb27a2e0dbf8608e2805cbe3f5b36 100644 --- a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java +++ b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java @@ -23,6 +23,7 @@ package de.kuschku.libquassel.localtypes.backlogstorage; import android.support.annotation.IntRange; import android.support.annotation.NonNull; +import android.util.Log; import android.util.SparseArray; import com.raizlabs.android.dbflow.config.FlowManager; @@ -99,6 +100,26 @@ public class HybridBacklogStorage implements BacklogStorage { }); } + @Override + public void insertMessages(@IntRange(from = 0) int bufferId, List<Message> messages) { + ensureExisting(bufferId); + FlowManager.getDatabase(ConnectedDatabase.class).executeTransaction(new ITransaction() { + @Override + public void execute(DatabaseWrapper databaseWrapper) { + for (Message message : messages) { + client.unbufferBuffer(message.bufferInfo); + synchronized (backlogs) { + if (backlogs.get(bufferId) != null) + backlogs.get(bufferId).add(message); + message.save(); + message.bufferInfo.save(); + } + updateLatest(message); + } + } + }); + } + public void updateLatest(@NonNull Message message) { if (message.id > getLatest(message.bufferInfo.id)) { latestMessage.put(message.bufferInfo.id, message.id); @@ -117,6 +138,18 @@ public class HybridBacklogStorage implements BacklogStorage { } } + @Override + public void insertMessages(List<Message> messages) { + for (Message message : messages) { + client.unbufferBuffer(message.bufferInfo); + synchronized (backlogs) { + if (backlogs.get(message.bufferInfo.id) != null) + backlogs.get(message.bufferInfo.id).add(message); + } + updateLatest(message); + } + } + public void setClient(Client client) { this.client = client; } @@ -134,7 +167,8 @@ public class HybridBacklogStorage implements BacklogStorage { @Override public void clear(@IntRange(from = 0) int bufferid) { - SQLite.delete().from(Message.class).where(Message_Table.bufferInfo_id.eq(bufferid)); + Log.w("libquassel", String.format("Backlog gap detected, clearing backlog for buffer %d", bufferid)); + SQLite.delete().from(Message.class).where(Message_Table.bufferInfo_id.eq(bufferid)).execute(); } private void ensureExisting(@IntRange(from = -1) int bufferId) { diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/MemoryBacklogStorage.java b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/MemoryBacklogStorage.java index 462354cb5c5b4831671e0d1ab3e3f44cf88a6787..fe0c2e4bab1786399fde3885bd51c6c3f60fb858 100644 --- a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/MemoryBacklogStorage.java +++ b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/MemoryBacklogStorage.java @@ -25,6 +25,8 @@ import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.util.SparseArray; +import java.util.List; + import de.kuschku.libquassel.client.Client; import de.kuschku.libquassel.localtypes.BacklogFilter; import de.kuschku.libquassel.message.Message; @@ -80,6 +82,16 @@ public class MemoryBacklogStorage implements BacklogStorage { } } + @Override + public void insertMessages(@IntRange(from = 0) int bufferId, List<Message> messages) { + ensureExisting(bufferId); + for (Message message : messages) { + client.unbufferBuffer(message.bufferInfo); + backlogs.get(bufferId).add(message); + updateLatest(message); + } + } + public void updateLatest(@NonNull Message message) { if (message.id > getLatest(message.bufferInfo.id)) { latestMessage.put(message.bufferInfo.id, message.id); @@ -96,6 +108,16 @@ public class MemoryBacklogStorage implements BacklogStorage { } } + @Override + public void insertMessages(List<Message> messages) { + for (Message message : messages) { + ensureExisting(message.bufferInfo.id); + client.unbufferBuffer(message.bufferInfo); + backlogs.get(message.bufferInfo.id).add(message); + updateLatest(message); + } + } + public void setClient(Client client) { this.client = client; } diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java index 62c97c1f063e10f3229cf8385040ba4cf830fa68..218528838ad031c5506290a2b10cfecdb0958da1 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java @@ -96,12 +96,10 @@ public class BacklogManager extends ABacklogManager<BacklogManager> { public void _receiveBacklog(int id, int first, int last, int limit, int additional, @NonNull List<Message> messages) { assertNotNull(provider); - Log.d("DEBUG", "Received " + messages.size() + " messages out of a max of " + limit); - Message lastMessageForBuffer = SQLite.select().from(Message.class).where(Message_Table.bufferInfo_id.eq(id)).orderBy(Message_Table.id, false).limit(1).querySingle(); - if (lastMessageForBuffer != null && messages.get(0).id > lastMessageForBuffer.id) + if (lastMessageForBuffer != null && messages.size() > 0 && messages.get(0).id > lastMessageForBuffer.id) storage.clear(id); - storage.insertMessages(id, messages.toArray(new Message[messages.size()])); + storage.insertMessages(id, messages); if (messages.size() > 0 && !client.bufferManager().exists(messages.get(0).bufferInfo)) client.bufferManager().createBuffer(messages.get(0).bufferInfo); provider.sendEvent(new BacklogReceivedEvent(id)); diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java index 9a8cf337aca4c01eb85e25fc67abbf944f9baedc..7174af59d85fce7076a12557bc9b3ccc9ec5f99c 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java @@ -21,6 +21,7 @@ package de.kuschku.quasseldroid_ng.ui.chat; +import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; @@ -28,6 +29,7 @@ import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.GravityCompat; +import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.AppCompatEditText; @@ -35,6 +37,7 @@ import android.support.v7.widget.AppCompatSpinner; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; @@ -43,10 +46,12 @@ import android.widget.AdapterView; import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; +import com.jakewharton.rxbinding.support.v7.widget.RxSearchView; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.TimeUnit; import butterknife.Bind; import butterknife.ButterKnife; @@ -76,6 +81,8 @@ import de.kuschku.util.accounts.AccountManager; import de.kuschku.util.certificates.CertificateUtils; import de.kuschku.util.certificates.SQLiteCertificateManager; import de.kuschku.util.servicebound.BoundActivity; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; import static de.kuschku.util.AndroidAssert.assertNotNull; @@ -112,6 +119,7 @@ public class MainActivity extends BoundActivity { private ToolbarWrapper toolbarWrapper; private BufferViewConfigAdapter chatListAdapter; + private Fragment currentFragment; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -178,6 +186,7 @@ public class MainActivity extends BoundActivity { private void replaceFragment(Fragment fragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + this.currentFragment = fragment; transaction.replace(R.id.content_host, fragment); transaction.commit(); } @@ -201,6 +210,16 @@ public class MainActivity extends BoundActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.chat, menu); + final SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search)); + SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE); + searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); + RxSearchView.queryTextChanges(searchView) + .debounce(400, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(charSequence -> { + if (context.client() != null) + context.client().backlogStorage().getFilter(context.client().backlogManager().open()).setQuery(charSequence); + }); return super.onCreateOptionsMenu(menu); } @@ -299,7 +318,6 @@ public class MainActivity extends BoundActivity { } } - /* private void updateBufferViewConfigs() { assertNotNull(context.client().bufferViewManager()); @@ -321,6 +339,13 @@ public class MainActivity extends BoundActivity { } */ + @Override + public void onBackPressed() { + if (!(currentFragment instanceof ChatFragment) || ((ChatFragment) currentFragment).onBackPressed()) { + super.onBackPressed(); + } + } + @Override protected void onConnectToThread(@Nullable ClientBackgroundThread thread) { super.onConnectToThread(thread); diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java index ffddc785636fa740a3a76a753015ad83e6f987a6..683444a2629487fca9566605d0d92bbff6fe21e2 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java @@ -188,7 +188,7 @@ public class ChatMessageRenderer { private void onBindQuit(@NonNull MessageViewHolder holder, @NonNull Message message) { applyStyle(holder, serverStyle, highlightStyle, message.flags.Highlight); - if (message.content.isEmpty()) + if (message.content == null || message.content.isEmpty()) holder.content.setText(context.themeUtil().translations.formatQuit( formatNick(message.sender) )); @@ -205,12 +205,14 @@ public class ChatMessageRenderer { holder.content.setText(context.themeUtil().translations.formatKick( formatNick(message.sender), message.content.substring(0, message.content.indexOf(" ")), + getBufferName(message), message.content.substring(message.content.indexOf(" ") + 1) )); else holder.content.setText(context.themeUtil().translations.formatKick( formatNick(message.sender), - message.content + message.content, + getBufferName(message) )); } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java index 5fc78b2f33fdeec993d39f5f3479057a14ba0b4a..ba5cfdbee2c524f29b5da9be312a7c4532082a0b 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java @@ -24,14 +24,13 @@ package de.kuschku.quasseldroid_ng.ui.chat.fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; -import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AbsListView; import com.sothree.slidinguppanel.SlidingUpPanelLayout; @@ -84,6 +83,7 @@ public class ChatFragment extends BoundFragment { messageAdapter = new MessageAdapter(getActivity(), context, new AutoScroller(messages)); messages.setAdapter(messageAdapter); + final int measuredHeight = messages.getMeasuredHeight(); messages.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { @@ -95,7 +95,12 @@ public class ChatFragment extends BoundFragment { backlogManager.requestMoreBacklog(client.backlogManager().open(), 20); loading = true; } - scrollDown.setVisibility(recyclerView.canScrollVertically(1) ? View.VISIBLE : View.GONE); + boolean canScrollDown = recyclerView.canScrollVertically(1); + boolean isScrollingDown = dy > 0; + int scrollOffsetFromBottom = recyclerView.computeVerticalScrollRange() - recyclerView.computeVerticalScrollOffset() - measuredHeight; + boolean isMoreThanOneScreenFromBottom = scrollOffsetFromBottom > measuredHeight; + boolean smartVisibility = scrollDown.getVisibility() == View.VISIBLE || isMoreThanOneScreenFromBottom; + scrollDown.setVisibility((canScrollDown && isScrollingDown && smartVisibility) ? View.VISIBLE : View.GONE); } }); @@ -143,4 +148,13 @@ public class ChatFragment extends BoundFragment { loading = false; } } + + public boolean onBackPressed() { + if (sliderMain.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + sliderMain.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + return false; + } else { + return true; + } + } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java index 5735b9a91b7978f9404a84a80f8d5e56b87fb483..ef37d40daade5e85c5d116192358039beb4bb3c3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java @@ -22,9 +22,6 @@ package de.kuschku.quasseldroid_ng.ui.chat.util; import android.app.Activity; -import android.graphics.Color; -import android.support.annotation.ColorInt; -import android.support.annotation.FloatRange; import android.support.v7.widget.ActionMenuView; import android.support.v7.widget.AppCompatEditText; import android.support.v7.widget.AppCompatImageButton; @@ -79,6 +76,7 @@ public class SlidingPanelHandler { AppCompatEditText chatline; @Bind(R.id.send) AppCompatImageButton send; + private ItemAdapter<IItem> previousMessages; public SlidingPanelHandler(Activity activity, SlidingUpPanelLayout slidingLayout, AppContext context) { this.slidingLayout = slidingLayout; @@ -152,42 +150,12 @@ public class SlidingPanelHandler { chatline.setSelection(selectionStart, selectionEnd); } - private int combineColors(@ColorInt int colora, @ColorInt int colorb, @FloatRange(from = 0.0, to = 1.0) float offset) { - float invOffset = 1 - offset; - - double alphaA = Math.pow(Color.alpha(colora), 2); - double alphaB = Math.pow(Color.alpha(colorb), 2); - - double redA = Math.pow(Color.red(colora), 2); - double redB = Math.pow(Color.red(colorb), 2); - - double greenA = Math.pow(Color.green(colora), 2); - double greenB = Math.pow(Color.green(colorb), 2); - - double blueA = Math.pow(Color.blue(colora), 2); - double blueB = Math.pow(Color.blue(colorb), 2); - - return Color.argb( - (int) Math.sqrt(alphaA * invOffset + alphaB * offset), - (int) Math.sqrt(redA * invOffset + redB * offset), - (int) Math.sqrt(greenA * invOffset + greenB * offset), - (int) Math.sqrt(blueA * invOffset + blueB * offset) - ); - } - private void bindListener() { slidingLayout.setAntiDragView(R.id.card_panel); slidingLayout.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() { @Override public void onPanelSlide(View panel, float slideOffset) { - /* - slidingLayoutHistory.setBackgroundColor(combineColors( - context.themeUtil().res.colorBackgroundCard, - context.themeUtil().res.colorBackground, - slideOffset - )); - */ } @Override @@ -237,31 +205,14 @@ public class SlidingPanelHandler { context.client().sendInput(buffer.getInfo(), text); chatline.setText(""); chatline.requestFocus(); + previousMessages.add(new PrimaryDrawerItem().withName(text)); } } private void setupHistoryFakeData() { FastAdapter<IItem> fastAdapter = new FastAdapter<>(); - ItemAdapter<IItem> itemAdapter = new ItemAdapter<>(); - itemAdapter.wrap(fastAdapter); - itemAdapter.add( - new PrimaryDrawerItem().withName("Entry #1"), - new PrimaryDrawerItem().withName("Entry #2"), - new PrimaryDrawerItem().withName("Entry #3"), - new PrimaryDrawerItem().withName("Entry #4"), - new PrimaryDrawerItem().withName("Entry #5"), - new PrimaryDrawerItem().withName("Entry #6"), - new PrimaryDrawerItem().withName("Entry #7"), - new PrimaryDrawerItem().withName("Entry #8"), - new PrimaryDrawerItem().withName("Entry #9"), - new PrimaryDrawerItem().withName("Entry #10"), - new PrimaryDrawerItem().withName("Entry #11"), - new PrimaryDrawerItem().withName("Entry #12"), - new PrimaryDrawerItem().withName("Entry #13"), - new PrimaryDrawerItem().withName("Entry #14"), - new PrimaryDrawerItem().withName("Entry #15"), - new PrimaryDrawerItem().withName("Entry #16") - ); + previousMessages = new ItemAdapter<>(); + previousMessages.wrap(fastAdapter); msgHistory.setAdapter(fastAdapter); msgHistory.setLayoutManager(new LinearLayoutManager(activity)); msgHistory.setItemAnimator(new DefaultItemAnimator()); diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java index 481985a3177c3ba244b95b499658ad8b098a3084..818c1a9d6f3fcf8e8001df19f3f7b87e935b3631 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java @@ -663,15 +663,15 @@ public class ThemeUtil { } @NonNull - public CharSequence formatKick(@NonNull CharSequence user, @NonNull CharSequence kicked) { - return SpanFormatter.format(messageKick, user, kicked); + public CharSequence formatKick(@NonNull CharSequence user, @NonNull CharSequence kicked, @NonNull CharSequence channel) { + return SpanFormatter.format(messageKick, user, kicked, channel); } @NonNull - public CharSequence formatKick(@NonNull CharSequence user, @NonNull CharSequence kicked, @Nullable CharSequence reason) { - if (reason == null || reason.length() == 0) return formatKick(user, kicked); + public CharSequence formatKick(@NonNull CharSequence user, @NonNull CharSequence kicked, @Nullable CharSequence reason, @NonNull CharSequence channel) { + if (reason == null || reason.length() == 0) return formatKick(user, kicked, channel); - return SpanFormatter.format(messageKickExtra, user, kicked, reason); + return SpanFormatter.format(messageKickExtra, user, kicked, reason, channel); } @NonNull diff --git a/app/src/main/java/de/kuschku/util/irc/format/IrcFormatDeserializer.java b/app/src/main/java/de/kuschku/util/irc/format/IrcFormatDeserializer.java index 3221e2171f9b9ef3fb53a2893bf56092ccc3905d..9c57fca6944b70b15bf0c7dce0382db7b888ee01 100644 --- a/app/src/main/java/de/kuschku/util/irc/format/IrcFormatDeserializer.java +++ b/app/src/main/java/de/kuschku/util/irc/format/IrcFormatDeserializer.java @@ -122,10 +122,14 @@ public class IrcFormatDeserializer { boolean colorize = context.settings().preferenceColors.get(); // Iterating over every character + int normalCount = 0; for (int i = 0; i < str.length(); i++) { char character = str.charAt(i); switch (character) { case CODE_BOLD: { + plainText.append(str.substring(i - normalCount, i)); + normalCount = 0; + // If there is an element on stack with the same code, close it if (bold != null) { if (colorize) bold.apply(plainText, plainText.length()); @@ -139,6 +143,9 @@ public class IrcFormatDeserializer { } break; case CODE_ITALIC: { + plainText.append(str.substring(i - normalCount, i)); + normalCount = 0; + // If there is an element on stack with the same code, close it if (italic != null) { if (colorize) italic.apply(plainText, plainText.length()); @@ -152,6 +159,9 @@ public class IrcFormatDeserializer { } break; case CODE_UNDERLINE: { + plainText.append(str.substring(i - normalCount, i)); + normalCount = 0; + // If there is an element on stack with the same code, close it if (underline != null) { if (colorize) underline.apply(plainText, plainText.length()); @@ -165,6 +175,9 @@ public class IrcFormatDeserializer { } break; case CODE_COLOR: { + plainText.append(str.substring(i - normalCount, i)); + normalCount = 0; + int foregroundStart = i + 1; int foregroundEnd = findEndOfNumber(str, foregroundStart); // If we have a foreground element @@ -200,6 +213,9 @@ public class IrcFormatDeserializer { } break; case CODE_SWAP: { + plainText.append(str.substring(i - normalCount, i)); + normalCount = 0; + // If we have a color tag before, apply it, and create a new one with swapped colors if (color != null) { if (colorize) color.apply(plainText, plainText.length()); @@ -208,6 +224,9 @@ public class IrcFormatDeserializer { } break; case CODE_RESET: { + plainText.append(str.substring(i - normalCount, i)); + normalCount = 0; + // End all formatting tags if (bold != null) { if (colorize) bold.apply(plainText, plainText.length()); @@ -229,7 +248,7 @@ public class IrcFormatDeserializer { break; default: { // Just append it, if it’s not special - plainText.append(character); + normalCount++; } } } @@ -247,6 +266,7 @@ public class IrcFormatDeserializer { if (color != null) { if (colorize) color.apply(plainText, plainText.length()); } + plainText.append(str.substring(str.length() - normalCount, str.length())); return plainText; } diff --git a/app/src/main/res/layout/widget_slider.xml b/app/src/main/res/layout/widget_slider.xml index 9d4a0fbb5debaed310ad33740ec894f763b953f3..812fa9d2d5bfd8b3d245620e5a7abbff521f281f 100644 --- a/app/src/main/res/layout/widget_slider.xml +++ b/app/src/main/res/layout/widget_slider.xml @@ -43,12 +43,12 @@ <FrameLayout android:id="@+id/card_panel" android:layout_width="fill_parent" - android:layout_height="wrap_content"> + android:layout_height="fill_parent"> <android.support.v7.widget.CardView style="?attr/cardStyle" android:layout_width="fill_parent" - android:layout_height="wrap_content" + android:layout_height="fill_parent" android:layout_marginBottom="16.0dip" android:layout_marginLeft="16.0dip" android:layout_marginRight="16.0dip" @@ -57,7 +57,7 @@ <LinearLayout android:layout_width="fill_parent" - android:layout_height="wrap_content" + android:layout_height="fill_parent" android:orientation="vertical"> <TextView @@ -73,7 +73,7 @@ <android.support.v7.widget.RecyclerView android:id="@+id/msg_history" android:layout_width="fill_parent" - android:layout_height="wrap_content" /> + android:layout_height="fill_parent" /> </LinearLayout> </android.support.v7.widget.CardView> </FrameLayout> diff --git a/app/src/main/res/menu/chat.xml b/app/src/main/res/menu/chat.xml index 734041b964f5ea5ad0a878eb2f7be7e60c173892..7381ab76409982bdd8da3e0639892a48b0064e7d 100644 --- a/app/src/main/res/menu/chat.xml +++ b/app/src/main/res/menu/chat.xml @@ -26,13 +26,18 @@ android:id="@+id/action_hide_events" android:icon="?attr/iconFilter" android:title="@string/labelHideEvents" - app:showAsAction="ifRoom" /> + app:showAsAction="never" /> + <item + android:id="@+id/action_search" + android:title="@string/label_search" + app:showAsAction="never|collapseActionView" + app:actionViewClass="android.support.v7.widget.SearchView" /> <item android:id="@+id/action_settings" - android:title="Settings" + android:title="@string/label_settings" app:showAsAction="never" /> <item android:id="@+id/action_reauth" - android:title="Disconnect" + android:title="@string/label_disconnect" app:showAsAction="never" /> </menu> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d94f0e3a04d545b6ebf2d342f04cfb41a9767b22..ae9968bb3858372aed8c48606d58f89b91910b11 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -81,4 +81,7 @@ <string name="statusWelcome">Welcome!</string> <string name="statusDisconnected">Connection lost</string> <string name="notification_report_crash">Reporting Crashes</string> + <string name="label_settings">Settings</string> + <string name="label_search">Find in Buffer</string> + <string name="label_disconnect">Disconnect</string> </resources>