diff --git a/.gitmodules b/.gitmodules index fb66a1d89c5dd2cdcb6b54df72c40882f0f3ff2d..5d4529c102bae6705be6292c8a1425ebb2932645 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "AndroidSlidingUpPanel"] path = AndroidSlidingUpPanel url = https://github.com/justjanne/AndroidSlidingUpPanel -[submodule "aspm"] - path = aspm - url = https://github.com/justjanne/aspm diff --git a/app/build.gradle b/app/build.gradle index 326276be94914deb501712eefbef16d2f18668f6..dc2a506526a2b67124ded6d192678f11284e7ee6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -153,12 +153,9 @@ dependencies { compile 'com.android.support:design:23.1.1' compile 'com.android.support:support-v4:23.1.1' compile 'com.android.support:recyclerview-v7:23.1.1' + compile 'com.android.support:preference-v14:23.1.1' compile 'com.android.support:cardview-v7:23.1.1' - // Setting autobinding - compile(name:'annotations', ext:'jar') - apt(name:'compiler-all', ext:'jar') - // UI autobinding compile 'com.jakewharton:butterknife:8.0.0-SNAPSHOT' apt 'com.jakewharton:butterknife-compiler:8.0.0-SNAPSHOT' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 81f3e83991ebf02234a322ed2b3ae4986538cbdb..32df2367fd107322107696e480db1fb3cce910be 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -32,10 +32,11 @@ android:icon="@mipmap/ic_launcher" android:label="@string/appName" android:supportsRtl="true"> + <service android:name=".service.QuasselService" /> <activity - android:name=".ui.chat.ChatActivity" + android:name=".ui.LoginActivity" android:label="@string/appName" android:launchMode="singleTask" android:theme="@style/AppTheme.Light"> @@ -45,6 +46,24 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + + <activity + android:name=".ui.chat.MainActivity" + android:label="@string/appName" + android:launchMode="singleTask" + android:theme="@style/AppTheme.Light" /> + + <activity + android:name=".ui.setup.AccountSetupActivity" + android:label="Setup a new Account" + android:launchMode="singleTask" + android:theme="@style/SetupTheme" /> + + <activity + android:name=".ui.setup.AccountSelectActivity" + android:label="Select an Account" + android:launchMode="singleTask" + android:theme="@style/SetupTheme" /> </application> </manifest> diff --git a/app/src/main/java/de/kuschku/libquassel/BusProvider.java b/app/src/main/java/de/kuschku/libquassel/BusProvider.java index 61069b8d39db4cf89e7a161e71b939c579014a8a..47fc9be9e54441440487f6c4482df8ef6b32cd68 100644 --- a/app/src/main/java/de/kuschku/libquassel/BusProvider.java +++ b/app/src/main/java/de/kuschku/libquassel/BusProvider.java @@ -28,6 +28,7 @@ import java.util.UUID; import de.greenrobot.event.EventBus; import de.greenrobot.event.NoSubscriberEvent; +import de.kuschku.libquassel.events.GeneralErrorEvent; public class BusProvider { @NonNull @@ -83,6 +84,10 @@ public class BusProvider { this.identifier = identifier; } + public void onEvent(GeneralErrorEvent event) { + Log.e(identifier, event.getClass().getSimpleName(), event.exception); + } + public void onEvent(NoSubscriberEvent event) { Log.e(identifier, String.valueOf(event)); } diff --git a/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java b/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java index c6026667c27094b190ca1b9623029fc5f3a1df69..328dc8531c8370a4f3d544611f19ab8f1bcdd608 100644 --- a/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java +++ b/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java @@ -25,6 +25,8 @@ import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import com.google.common.collect.Sets; + import java.util.HashMap; import java.util.HashSet; import java.util.List; diff --git a/app/src/main/java/de/kuschku/libquassel/client/Client.java b/app/src/main/java/de/kuschku/libquassel/client/Client.java index 1b3597e9b49c7a204697dd2b528399d1482c45ad..21104c93b9470e5be9dd5e3d9bcc5a6bd60d2971 100644 --- a/app/src/main/java/de/kuschku/libquassel/client/Client.java +++ b/app/src/main/java/de/kuschku/libquassel/client/Client.java @@ -200,7 +200,7 @@ public class Client extends AClient { } else if (connectionStatus == ConnectionChangeEvent.Status.CONNECTED) { // FIXME: Init buffer activity state and highlightss } - provider.sendEvent(new ConnectionChangeEvent(connectionStatus)); + provider.event.postSticky(new ConnectionChangeEvent(connectionStatus)); } @Nullable @@ -318,6 +318,9 @@ public class Client extends AClient { requestInitObject("IgnoreListManager", ""); //sendInitRequest("TransferManager", ""); // This thing never gets sent... + + assertNotNull(provider); + provider.event.postSticky(new InitEvent(initRequestMax - initRequests.size(), initRequestMax)); } @NonNull @@ -349,16 +352,16 @@ public class Client extends AClient { public void initObject(String className, @NonNull String objectName, @NonNull SyncableObject object) { assertNotNull(provider); + object.init(objectName, provider, this); + if (connectionStatus() == ConnectionChangeEvent.Status.INITIALIZING_DATA) { initRequests.remove(hashName(className, objectName)); - provider.sendEvent(new InitEvent(initRequestMax - initRequests.size(), initRequestMax)); + provider.event.postSticky(new InitEvent(initRequestMax - initRequests.size(), initRequestMax)); if (initRequests.isEmpty()) { setConnectionStatus(ConnectionChangeEvent.Status.LOADING_BACKLOG); } } - object.init(objectName, provider, this); - // Execute cached sync requests if (bufferedSyncs.size() > 0) { String key = hashName(className, objectName); diff --git a/app/src/main/java/de/kuschku/libquassel/events/BufferChangeEvent.java b/app/src/main/java/de/kuschku/libquassel/events/BufferChangeEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..2cef25718845eec5128c70e091b5232648ce9511 --- /dev/null +++ b/app/src/main/java/de/kuschku/libquassel/events/BufferChangeEvent.java @@ -0,0 +1,25 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.libquassel.events; + +public class BufferChangeEvent { +} 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 f64af79214bd1e22e4b78750feb217f3483eb448..4fa6f80d735634b58205afeec33e896a5b64cbb0 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 @@ -33,6 +33,7 @@ import de.kuschku.libquassel.BusProvider; import de.kuschku.libquassel.client.Client; import de.kuschku.libquassel.events.BacklogInitEvent; import de.kuschku.libquassel.events.BacklogReceivedEvent; +import de.kuschku.libquassel.events.BufferChangeEvent; import de.kuschku.libquassel.events.ConnectionChangeEvent; import de.kuschku.libquassel.localtypes.BacklogFilter; import de.kuschku.libquassel.localtypes.backlogstorage.BacklogStorage; @@ -106,7 +107,7 @@ public class BacklogManager extends ABacklogManager<BacklogManager> { assertNotNull(provider); if (client.connectionStatus() == ConnectionChangeEvent.Status.LOADING_BACKLOG) { - provider.sendEvent(new BacklogInitEvent(waitingMax - waiting.size(), waitingMax)); + provider.event.postSticky(new BacklogInitEvent(waitingMax - waiting.size(), waitingMax)); if (waiting.isEmpty()) { client.setConnectionStatus(ConnectionChangeEvent.Status.CONNECTED); } @@ -157,9 +158,17 @@ public class BacklogManager extends ABacklogManager<BacklogManager> { @Override public void open(int bufferId) { + assertNotNull(provider); + openBuffer = bufferId; if (bufferId != -1) client.bufferSyncer().requestMarkBufferAsRead(bufferId); + provider.sendEvent(new BufferChangeEvent()); + } + + @Override + public int open() { + return openBuffer; } @Override diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java index 14414e07205974fb8dfe1590638e1428e8061754..962f1c4f35b6735f60452378f2d3c0be97601f1f 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java @@ -163,7 +163,6 @@ public class BufferSyncer extends ABufferSyncer<BufferSyncer> { int lastMessage = client.backlogStorage().getLatest(buffer); if (lastMessage != -1) { requestSetLastSeenMsg(buffer, lastMessage); - requestSetMarkerLine(buffer, lastMessage); } } diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java index 5cf65c0a3c1d08939a616734d2ecb4de451208a7..0fee0b05e725ccd5e9b6ef623988229e469c4a2f 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java @@ -41,7 +41,7 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { @NonNull private final ObservableList<Integer> buffers; @NonNull - private final ObservableSet<Integer> buffersIds; + private final ObservableSet<Integer> bufferIds; @NonNull private final ObservableSet<Integer> removedBuffers; @NonNull @@ -62,8 +62,10 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { this.temporarilyRemovedBuffers = new ObservableSet<>(temporarilyRemovedBuffers); this.hideInactiveNetworks = hideInactiveNetworks; this.buffers = new ObservableList<>(buffers); - this.buffersIds = new ObservableSet<>(); - bufferIds().addAll(buffers); + buffers.removeAll(removedBuffers); + buffers.removeAll(temporarilyRemovedBuffers); + this.bufferIds = new ObservableSet<>(); + bufferIds.addAll(buffers); this.allowedBufferTypes = allowedBufferTypes; this.sortAlphabetically = sortAlphabetically; this.disableDecoration = disableDecoration; @@ -212,7 +214,7 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { @NonNull @Override public ObservableSet<Integer> bufferIds() { - return buffersIds; + return bufferIds; } @NonNull @@ -355,8 +357,8 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { this.hideInactiveNetworks = from.hideInactiveNetworks; this.buffers.clear(); this.buffers.addAll(from.buffers); - this.buffersIds.retainAll(from.buffersIds); - this.buffersIds.addAll(from.buffersIds); + this.bufferIds.retainAll(from.bufferIds); + this.bufferIds.addAll(from.bufferIds); this.removedBuffers.retainAll(from.removedBuffers); this.removedBuffers.addAll(from.removedBuffers); this.temporarilyRemovedBuffers.retainAll(from.temporarilyRemovedBuffers); diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java index d4d4f4864279634467cc6db46fb143b33f5cb208..b5904855f8b3952dbc97e2cb9a765d3c9014cbcf 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java @@ -66,6 +66,7 @@ public interface QBacklogManager<T extends QSyncableObject<T>> extends QSyncable ObservableComparableSortedList<Message> filtered(int id); void open(int bufferId); + int open(); void receiveBacklog(Message msg); diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java b/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java index d01c2b702825ccfa443f7fb6d0eb250af3749d44..3c31c7f8394fc401e4ae4006332ffd3cd6985637 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java @@ -31,8 +31,12 @@ import de.kuschku.libquassel.QuasselClient; import de.kuschku.libquassel.client.ClientData; import de.kuschku.libquassel.client.FeatureFlags; import de.kuschku.libquassel.events.GeneralErrorEvent; +import de.kuschku.libquassel.events.LoginRequireEvent; import de.kuschku.libquassel.localtypes.backlogstorage.MemoryBacklogStorage; import de.kuschku.libquassel.protocols.RemotePeer; +import de.kuschku.quasseldroid_ng.ui.chat.Settings; +import de.kuschku.quasseldroid_ng.util.accounts.Account; +import de.kuschku.quasseldroid_ng.util.accounts.AccountManager; import de.kuschku.util.CompatibilityUtils; import de.kuschku.util.ServerAddress; import de.kuschku.util.certificates.SQLiteCertificateManager; @@ -49,6 +53,9 @@ public class ClientBackgroundThread implements Runnable { @NonNull private final QuasselClient client; + private final Settings settings; + private final AccountManager manager; + public ClientBackgroundThread(@NonNull BusProvider provider, @NonNull ServerAddress address, @NonNull Context context) { this.client = new QuasselClient( provider, @@ -57,6 +64,10 @@ public class ClientBackgroundThread implements Runnable { new MemoryBacklogStorage() ); this.client.connect(address); + this.client.provider.event.registerSticky(this); + + settings = new Settings(context); + manager = new AccountManager(context); } @NonNull @@ -76,4 +87,11 @@ public class ClientBackgroundThread implements Runnable { public void close() { client.disconnect(); } + + public void onEvent(LoginRequireEvent event) { + if (!event.failedLast) { + Account account = manager.account(settings.lastAccount.get()); + client().client.login(account.user, account.pass); + } + } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java index d94c617f56dd6163739757e9e5571ae8fcc0dec9..8a75f4385d911b00da17b8f21a0e820c5b0e0419 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java @@ -28,8 +28,12 @@ import android.os.IBinder; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import java.util.HashSet; +import java.util.Set; + import de.kuschku.libquassel.BusProvider; import de.kuschku.util.ServerAddress; +import de.kuschku.util.backports.Consumer; public class QuasselService extends Service { @NonNull @@ -38,6 +42,8 @@ public class QuasselService extends Service { @Nullable private ClientBackgroundThread bgThread; + private Set<Consumer<ClientBackgroundThread>> consumers = new HashSet<>(); + @Override public IBinder onBind(Intent intent) { return binder; @@ -52,6 +58,7 @@ public class QuasselService extends Service { public void startBackgroundThread(@NonNull BusProvider provider, @NonNull ServerAddress address) { bgThread = new ClientBackgroundThread(provider, address, QuasselService.this); new Thread(bgThread).start(); + notify(bgThread); } @Nullable @@ -62,6 +69,19 @@ public class QuasselService extends Service { public void stopBackgroundThread() { if (bgThread != null) bgThread.close(); bgThread = null; + notify(bgThread); + } + + public void addCallback(Consumer<ClientBackgroundThread> consumer) { + consumers.add(consumer); + } + public void removeCallback(Consumer<ClientBackgroundThread> consumer) { + consumers.remove(consumer); + } + private void notify(ClientBackgroundThread thread) { + for (Consumer<ClientBackgroundThread> consumer : consumers) { + consumer.apply(thread); + } } } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/LoginActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/LoginActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..c690cd62b2d6da8ebc03e034bf35340b049b477e --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/LoginActivity.java @@ -0,0 +1,82 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; + +import de.kuschku.quasseldroid_ng.ui.chat.MainActivity; +import de.kuschku.quasseldroid_ng.ui.chat.Settings; +import de.kuschku.quasseldroid_ng.ui.chat.util.ServiceHelper; +import de.kuschku.quasseldroid_ng.ui.setup.AccountSelectActivity; +import de.kuschku.quasseldroid_ng.ui.theme.AppContext; + +public class LoginActivity extends AppCompatActivity { + private AppContext context = new AppContext(); + + private boolean firstStart = true; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ServiceHelper.initTheme(context, this); + context.withSettings(new Settings(this)); + } + + @Override + protected void onResume() { + super.onResume(); + if (!checkReady()) { + finish(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + context.settings().lastAccount.set(data.getBundleExtra("extra").getString("account")); + checkReady(); + firstStart = true; + } else if (context.settings().lastAccount.get().isEmpty()) { + finish(); + } + } + + private boolean checkReady() { + if (context.settings().lastAccount.get().isEmpty()) { + Intent intent = new Intent(this, AccountSelectActivity.class); + startActivityForResult(intent, 0); + firstStart = true; + return true; + } else if (firstStart) { + startActivity(new Intent(this, MainActivity.class)); + firstStart = false; + return true; + } else { + return false; + } + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java deleted file mode 100644 index 65af818a6dd6e87893f101fc821929b51250ca09..0000000000000000000000000000000000000000 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java +++ /dev/null @@ -1,902 +0,0 @@ -/* - * QuasselDroid - Quassel client for Android - * Copyright (C) 2016 Janne Koschinski - * Copyright (C) 2016 Ken Børge Viktil - * Copyright (C) 2016 Magnus Fjell - * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package de.kuschku.quasseldroid_ng.ui.chat; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.IBinder; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.UiThread; -import android.support.design.widget.Snackbar; -import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.ActionMenuView; -import android.support.v7.widget.AppCompatEditText; -import android.support.v7.widget.AppCompatImageButton; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.Gravity; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ScrollView; - -import com.afollestad.materialdialogs.MaterialDialog; -import com.google.common.base.Splitter; -import com.mikepenz.fastadapter.FastAdapter; -import com.mikepenz.fastadapter.IExpandable; -import com.mikepenz.fastadapter.IItem; -import com.mikepenz.fastadapter.adapters.ItemAdapter; -import com.mikepenz.materialdrawer.AccountHeader; -import com.mikepenz.materialdrawer.AccountHeaderBuilder; -import com.mikepenz.materialdrawer.Drawer; -import com.mikepenz.materialdrawer.DrawerBuilder; -import com.mikepenz.materialdrawer.model.PrimaryDrawerItem; -import com.mikepenz.materialdrawer.model.ProfileDrawerItem; -import com.mikepenz.materialdrawer.model.SecondaryDrawerItem; -import com.sothree.slidinguppanel.SlidingUpPanelLayout; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import aspm.annotations.BooleanPreference; -import aspm.annotations.IntPreference; -import aspm.annotations.PreferenceWrapper; -import aspm.annotations.StringPreference; -import butterknife.Bind; -import butterknife.ButterKnife; -import de.kuschku.libquassel.BusProvider; -import de.kuschku.libquassel.client.Client; -import de.kuschku.libquassel.events.BacklogInitEvent; -import de.kuschku.libquassel.events.BacklogReceivedEvent; -import de.kuschku.libquassel.events.ConnectionChangeEvent; -import de.kuschku.libquassel.events.GeneralErrorEvent; -import de.kuschku.libquassel.events.InitEvent; -import de.kuschku.libquassel.events.LagChangedEvent; -import de.kuschku.libquassel.events.LoginRequireEvent; -import de.kuschku.libquassel.events.UnknownCertificateEvent; -import de.kuschku.libquassel.localtypes.BacklogFilter; -import de.kuschku.libquassel.localtypes.buffers.Buffer; -import de.kuschku.libquassel.localtypes.buffers.ChannelBuffer; -import de.kuschku.libquassel.message.Message; -import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager; -import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig; -import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager; -import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel; -import de.kuschku.quasseldroid_ng.BuildConfig; -import de.kuschku.quasseldroid_ng.R; -import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread; -import de.kuschku.quasseldroid_ng.service.QuasselService; -import de.kuschku.quasseldroid_ng.ui.chat.chatview.MessageAdapter; -import de.kuschku.quasseldroid_ng.ui.chat.drawer.BufferItem; -import de.kuschku.quasseldroid_ng.ui.chat.drawer.BufferViewConfigItem; -import de.kuschku.quasseldroid_ng.ui.editor.AdvancedEditor; -import de.kuschku.quasseldroid_ng.ui.theme.AppContext; -import de.kuschku.quasseldroid_ng.ui.theme.AppTheme; -import de.kuschku.quasseldroid_ng.ui.theme.ThemeUtil; -import de.kuschku.util.ServerAddress; -import de.kuschku.util.certificates.CertificateUtils; -import de.kuschku.util.instancestateutil.Storable; -import de.kuschku.util.instancestateutil.Store; -import de.kuschku.util.observables.AutoScroller; -import de.kuschku.util.observables.lists.ObservableSortedList; - -import static de.kuschku.util.AndroidAssert.assertNotNull; - -@UiThread -public class ChatActivity extends AppCompatActivity { - @NonNull - private final Status status = new Status(); - @NonNull - private final ServiceInterface serviceInterface = new ServiceInterface(); - @NonNull - private final AppContext context = new AppContext(); - // Main layout - @Bind(R.id.toolbar) - Toolbar toolbar; - @Bind(R.id.sliding_layout) - SlidingUpPanelLayout slidingLayout; - // Input Line - @Bind(R.id.chatline_scroller) - ScrollView chatlineScroller; - @Bind(R.id.chatline) - AppCompatEditText chatline; - @Bind(R.id.send) - AppCompatImageButton send; - // Input History - @Bind(R.id.sliding_layout_history) - SlidingUpPanelLayout slidingLayoutHistory; - @Bind(R.id.msg_history) - RecyclerView msgHistory; - // Advanced Formatter - @Bind(R.id.formatting_menu) - ActionMenuView formattingMenu; - @Bind(R.id.formatting_toolbar) - Toolbar formattingToolbar; - // Content view - @Bind(R.id.swipe_view) - SwipeRefreshLayout swipeView; - @Bind(R.id.messages) - RecyclerView messages; - private MessageAdapter messageAdapter; - private AccountHeader accountHeader; - private Drawer drawerLeft; - private Drawer drawerRight; - private AdvancedEditor editor; - @Nullable - private QuasselService.LocalBinder binder; - @Nullable - private final ServiceConnection serviceConnection = new ServiceConnection() { - @UiThread - public void onServiceConnected(ComponentName cn, IBinder service) { - assertNotNull(cn); - assertNotNull(service); - - if (service instanceof QuasselService.LocalBinder) { - ChatActivity.this.binder = (QuasselService.LocalBinder) service; - if (binder != null && binder.getBackgroundThread() != null) { - ClientBackgroundThread backgroundThread = binder.getBackgroundThread(); - assertNotNull(backgroundThread); - - serviceInterface.disconnect(); - - BusProvider provider = backgroundThread.client().provider; - Client client = backgroundThread.client().client; - context.setProvider(provider); - context.setClient(client); - provider.event.register(ChatActivity.this); - - - updateSubTitle(); - if (client.connectionStatus() == ConnectionChangeEvent.Status.CONNECTED) { - updateBufferViewConfigs(); - } - } - } - } - - @UiThread - public void onServiceDisconnected(ComponentName cn) { - assertNotNull(cn); - - serviceInterface.disconnect(); - binder = null; - } - }; - - private static void updateNoColor(@Nullable Buffer buffer, @NonNull Menu menu) { - boolean isNoColor = isNoColor(buffer); - MenuItem item_bold = menu.findItem(R.id.format_bold); - if (item_bold != null) - item_bold.setEnabled(!isNoColor); - MenuItem item_italic = menu.findItem(R.id.format_italic); - if (item_italic != null) - item_italic.setEnabled(!isNoColor); - MenuItem item_underline = menu.findItem(R.id.format_underline); - if (item_underline != null) - item_underline.setEnabled(!isNoColor); - MenuItem item_paint = menu.findItem(R.id.format_paint); - if (item_paint != null) - item_paint.setEnabled(!isNoColor); - MenuItem item_fill = menu.findItem(R.id.format_fill); - if (item_fill != null) - item_fill.setEnabled(!isNoColor); - } - - public static boolean isNoColor(@Nullable Buffer buffer) { - if (buffer == null) - return false; - if (!(buffer instanceof ChannelBuffer)) - return false; - QIrcChannel channel = ((ChannelBuffer) buffer).getChannel(); - return channel != null && channel.hasMode('c'); - } - - private void updateSubTitle() { - Client client = context.client(); - if (client != null) { - ConnectionChangeEvent.Status status = client.connectionStatus(); - if (status == ConnectionChangeEvent.Status.CONNECTED) { - if (this.status.bufferId > 0) { - Buffer buffer = client.bufferManager().buffer(this.status.bufferId); - if (buffer != null && buffer instanceof ChannelBuffer) { - QIrcChannel channel = ((ChannelBuffer) buffer).getChannel(); - if (channel != null) { - updateSubTitle(channel.topic()); - return; - } - } - } - } else if (status != null) { - updateSubTitle(status.name()); - return; - } - } - updateSubTitle(""); - } - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - setupContext(); - - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_chat); - ButterKnife.bind(this); - setSupportActionBar(toolbar); - - Intent intent = new Intent(this, QuasselService.class); - startService(intent); - - setupHeader(savedInstanceState); - - setupDrawer(savedInstanceState); - - setupEditor(); - - setupContent(); - - setupHistory(); - - initLoader(); - } - - @Override - protected void onPause() { - serviceInterface.disconnect(); - unbindService(serviceConnection); - super.onPause(); - } - - @Override - protected void onResume() { - super.onResume(); - Intent intent = new Intent(this, QuasselService.class); - bindService(intent, serviceConnection, Context.BIND_IMPORTANT); - } - - @Override - protected void onStart() { - super.onStart(); - } - - @Override - protected void onStop() { - super.onStop(); - } - - @Override - protected void onRestart() { - super.onRestart(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - assertNotNull(outState); - - super.onSaveInstanceState(outState); - status.onSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { - assertNotNull(savedInstanceState); - - super.onRestoreInstanceState(savedInstanceState); - status.onRestoreInstanceState(savedInstanceState); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.chat, menu); - return super.onCreateOptionsMenu(menu); - } - - // FIXME: REWRITE - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - assertNotNull(item); - - List<Integer> filterSettings = Arrays.asList( - Message.Type.Join.value, - Message.Type.Part.value, - Message.Type.Quit.value, - Message.Type.Nick.value, - Message.Type.Mode.value, - Message.Type.Topic.value - ); - int[] filterSettingsInts = new int[filterSettings.size()]; - for (int i = 0; i < filterSettingsInts.length; i++) { - filterSettingsInts[i] = filterSettings.get(i); - } - - switch (item.getItemId()) { - case R.id.action_hide_events: { - if (context.client() != null) { - BacklogFilter backlogFilter = context.client().backlogManager().filter(status.bufferId); - if (backlogFilter != null) { - int oldFilters = backlogFilter.getFilters(); - List<Integer> oldFiltersList = new ArrayList<>(); - for (int type : filterSettings) { - if ((type & oldFilters) != 0) - oldFiltersList.add(filterSettings.indexOf(type)); - } - Integer[] selectedIndices = oldFiltersList.toArray(new Integer[oldFiltersList.size()]); - new MaterialDialog.Builder(this) - .items( - "Joins", - "Parts", - "Quits", - "Nick Changes", - "Mode Changes", - "Topic Changes" - ) - .itemsIds(filterSettingsInts) - .itemsCallbackMultiChoice( - selectedIndices, - (dialog, which, text) -> false - ) - .positiveText("Select") - .negativeText("Cancel") - .onPositive((dialog, which) -> { - int filters = 0x00000000; - if (dialog.getSelectedIndices() != null) - for (int i : dialog.getSelectedIndices()) { - filters |= filterSettings.get(i); - } - backlogFilter.setFilters(filters); - }) - .build() - .show(); - } - } - } - } - return super.onOptionsItemSelected(item); - } - - private void setupContext() { - WrappedSettings settings = new WrappedSettings(this); - context.setSettings(settings); - AppTheme theme = AppTheme.themeFromString(settings.theme.get()); - setTheme(theme.themeId); - context.setThemeUtil(new ThemeUtil(this, theme)); - } - - private void setupEditorLayout() { - assertNotNull(slidingLayout); - - slidingLayout.setAntiDragView(R.id.card_panel); - slidingLayout.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() { - @Override - public void onPanelSlide(View panel, float slideOffset) { - - } - - @Override - public void onPanelCollapsed(View panel) { - setChatlineExpanded(false); - } - - @Override - public void onPanelExpanded(View panel) { - setChatlineExpanded(true); - } - - @Override - public void onPanelAnchored(View panel) { - - } - - @Override - public void onPanelHidden(View panel) { - - } - }); - setChatlineExpanded(slidingLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED); - } - - private void initLoader() { - assertNotNull(swipeView); - ThemeUtil themeUtil = context.themeUtil(); - assertNotNull(themeUtil); - - - swipeView.setEnabled(false); - swipeView.setColorSchemeColors(themeUtil.res.colorPrimary); - swipeView.setOnRefreshListener(() -> { - Client client = context.client(); - assertNotNull(client); - QBacklogManager<? extends QBacklogManager> backlogManager = client.backlogManager(); - assertNotNull(backlogManager); - backlogManager.requestMoreBacklog(status.bufferId, 20); - }); - } - - private void setupHistory() { - assertNotNull(msgHistory); - - 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") - ); - msgHistory.setAdapter(fastAdapter); - msgHistory.setLayoutManager(new LinearLayoutManager(this)); - msgHistory.setItemAnimator(new DefaultItemAnimator()); - } - - private void setupContent() { - assertNotNull(messages); - - messages.setItemAnimator(new DefaultItemAnimator()); - messages.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true)); - messageAdapter = new MessageAdapter(this, context, new AutoScroller(messages)); - messages.setAdapter(messageAdapter); - } - - private void setupEditor() { - assertNotNull(formattingMenu); - assertNotNull(slidingLayoutHistory); - assertNotNull(send); - assertNotNull(chatline); - - getMenuInflater().inflate(R.menu.formatting, formattingMenu.getMenu()); - formattingMenu.setOnMenuItemClickListener(item -> { - switch (item.getItemId()) { - case R.id.format_bold: - editor.toggleBold(); - return true; - case R.id.format_italic: - editor.toggleItalic(); - return true; - case R.id.format_underline: - editor.toggleUnderline(); - return true; - case R.id.action_history: - slidingLayoutHistory.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); - return true; - default: - return false; - } - }); - editor = new AdvancedEditor(context, chatline); - send.setOnClickListener(view -> sendInput()); - - setupEditorLayout(); - } - - private void setupDrawer(@Nullable Bundle savedInstanceState) { - drawerLeft = new DrawerBuilder() - .withActivity(this) - .withToolbar(toolbar) - .withAccountHeader(accountHeader) - .withSavedInstance(savedInstanceState) - .withTranslucentStatusBar(true) - .build(); - assertNotNull(drawerLeft); - assertNotNull(drawerLeft.getAdapter()); - drawerLeft.addStickyFooterItem(new PrimaryDrawerItem().withIcon(R.drawable.ic_server_light).withName("(Re-)Connect").withIdentifier(-1)); - drawerLeft.addStickyFooterItem(new SecondaryDrawerItem().withName("Settings").withIdentifier(-2)); - drawerLeft.setOnDrawerItemClickListener((view, position, drawerItem) -> { - long identifier = drawerItem.getIdentifier(); - if (identifier == -1) { - showConnectDialog(); - return false; - } else if (identifier == -2) { - showThemeDialog(); - return false; - } else { - if (((IExpandable) drawerItem).getSubItems() != null) { - drawerLeft.getAdapter().toggleExpandable(position); - return true; - } else if (drawerItem instanceof BufferItem) { - selectBuffer(((BufferItem) drawerItem).getBuffer().getInfo().id()); - return false; - } - return true; - } - }); - drawerRight = new DrawerBuilder() - .withActivity(this) - .withSavedInstance(savedInstanceState) - .withDrawerGravity(Gravity.END) - .build(); - } - - private void setupHeader(@Nullable Bundle savedInstanceState) { - accountHeader = new AccountHeaderBuilder() - .withActivity(this) - .withCompactStyle(true) - .withHeaderBackground(R.drawable.bg) - .withSavedInstance(savedInstanceState) - .withProfileImagesVisible(false) - .withOnAccountHeaderListener((view, profile, current) -> { - selectBufferViewConfig((int) profile.getIdentifier()); - return true; - }) - .build(); - } - - public void setChatlineExpanded(boolean expanded) { - assertNotNull(chatline); - assertNotNull(chatline.getLayoutParams()); - ThemeUtil themeUtil = context.themeUtil(); - assertNotNull(themeUtil); - - int selectionStart = chatline.getSelectionStart(); - int selectionEnd = chatline.getSelectionEnd(); - - if (expanded) { - chatline.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; - } else { - chatline.getLayoutParams().height = themeUtil.res.actionBarSize; - } - chatline.setSingleLine(!expanded); - - chatline.setSelection(selectionStart, selectionEnd); - } - - // FIXME: Rewrite properly - public void showThemeDialog() { - String[] strings = new String[AppTheme.values().length]; - int startIndex = -1; - for (int i = 0; i < strings.length; i++) { - AppTheme theme = AppTheme.values()[i]; - strings[i] = theme.name(); - if (theme.name().equals(context.settings().theme.get())) startIndex = i; - } - - new MaterialDialog.Builder(this) - .items(strings) - .positiveText("Select Theme") - .negativeText("Cancel") - .itemsCallbackSingleChoice(startIndex, (dialog, itemView, which, text) -> { - context.settings().theme.set(strings[dialog.getSelectedIndex()]); - recreate(); - return true; - }) - .negativeColor(context.themeUtil().res.colorForeground) - .build() - .show(); - } - - private void selectBufferViewConfig(@IntRange(from = -1) int bufferViewConfigId) { - assertNotNull(drawerLeft); - assertNotNull(accountHeader); - Client client = context.client(); - assertNotNull(client); - - status.bufferViewConfigId = bufferViewConfigId; - accountHeader.setActiveProfile(bufferViewConfigId, false); - - if (bufferViewConfigId == -1) { - drawerLeft.removeAllItems(); - } else { - drawerLeft.removeAllItems(); - QBufferViewManager bufferViewManager = client.bufferViewManager(); - assertNotNull(bufferViewManager); - QBufferViewConfig viewConfig = bufferViewManager.bufferViewConfig(bufferViewConfigId); - assertNotNull(viewConfig); - - new BufferViewConfigItem(drawerLeft, viewConfig, context); - } - } - - private void selectBuffer(@IntRange(from = -1) int bufferId) { - context.client().backlogManager().open(bufferId); - if (bufferId == -1) { - status.bufferId = bufferId; - swipeView.setEnabled(false); - context.client().backlogManager().open(bufferId); - - messageAdapter.setMessageList(MessageAdapter.emptyList()); - toolbar.setTitle(getResources().getString(R.string.appName)); - } else { - status.bufferId = bufferId; - swipeView.setEnabled(true); - context.client().backlogManager().open(bufferId); - - // Make sure we are actually connected - ObservableSortedList<Message> list = context.client().backlogManager().filtered(bufferId); - Buffer buffer = context.client().bufferManager().buffer(bufferId); - // Make sure everything is properly defined - assertNotNull("Buffer is null: " + bufferId, buffer); - assertNotNull(list); - - messageAdapter.setMessageList(list); - toolbar.setTitle(buffer.getName()); - updateNoColor(buffer, formattingMenu.getMenu()); - - if (buffer instanceof ChannelBuffer && ((ChannelBuffer) buffer).getChannel() != null) { - NickListWrapper nicklistwrapper = new NickListWrapper(drawerRight, ((ChannelBuffer) buffer).getChannel()); - } else { - drawerRight.removeAllItems(); - } - } - updateSubTitle(); - } - - private void onConnectionEstablished() { - assertNotNull(binder); - assertNotNull(binder.getBackgroundThread()); - context.setClient(binder.getBackgroundThread().client().client); - assertNotNull(context.client()); - } - - private void sendInput() { - if (context.client() == null) return; - - int bufferId = status.bufferId; - - if (bufferId >= 0) { - Buffer buffer = context.client().bufferManager().buffer(bufferId); - assertNotNull(buffer); - - String text = editor.toFormatString(); - context.client().sendInput(buffer.getInfo(), text); - chatline.setText(""); - } else { - Snackbar.make(messages, "No buffer opened", Snackbar.LENGTH_LONG).show(); - } - } - - public void onEventMainThread(@NonNull LoginRequireEvent event) { - assertNotNull(context.client()); - - if (event.failedLast) - showLoginDialog(); - else - context.client().login( - context.settings().lastUsername.or(""), - context.settings().lastPassword.or("") - ); - } - - public void onEventMainThread(@NonNull ConnectionChangeEvent event) { - updateSubTitle(); - - switch (event.status) { - case CONNECTED: - updateBufferViewConfigs(); - break; - } - } - - public void onEventMainThread(@NonNull BacklogInitEvent event) { - updateSubTitle(event.toString()); - } - - public void onEventMainThread(@NonNull InitEvent event) { - updateSubTitle(event.toString()); - } - - private void updateBufferViewConfigs() { - assertNotNull(context.client().bufferViewManager()); - List<QBufferViewConfig> bufferViews = context.client().bufferViewManager().bufferViewConfigs(); - accountHeader.clear(); - for (QBufferViewConfig viewConfig : bufferViews) { - if (viewConfig != null) { - accountHeader.addProfiles( - new ProfileDrawerItem() - .withName(viewConfig.bufferViewName()) - .withIdentifier(viewConfig.bufferViewId()) - ); - } - } - selectBufferViewConfig(status.bufferViewConfigId); - selectBuffer(status.bufferId); - } - - private void showLoginDialog() { - MaterialDialog dialog = new MaterialDialog.Builder(this) - .title(R.string.labelLogin) - .customView(R.layout.dialog_login, false) - .onPositive((dialog1, which) -> { - View parent = dialog1.getCustomView(); - assertNotNull(parent); - AppCompatEditText usernameField = (AppCompatEditText) parent.findViewById(R.id.username); - AppCompatEditText passwordField = (AppCompatEditText) parent.findViewById(R.id.password); - String username = usernameField.getText().toString(); - String password = passwordField.getText().toString(); - context.settings().lastUsername.set(username); - context.settings().lastPassword.set(password); - context.client().login(username, password); - }) - .cancelListener(dialog1 -> { - if (binder != null) - binder.stopBackgroundThread(); - serviceInterface.disconnect(); - }) - .negativeColor(context.themeUtil().res.colorForeground) - .positiveText(R.string.labelLogin) - .negativeText(R.string.labelCancel) - .build(); - ((AppCompatEditText) dialog.getView().findViewById(R.id.username)).setText(context.settings().lastUsername.get()); - ((AppCompatEditText) dialog.getView().findViewById(R.id.password)).setText(context.settings().lastPassword.get()); - dialog.show(); - } - - public void showConnectDialog() { - MaterialDialog dialog = new MaterialDialog.Builder(this) - .title(R.string.labelAddress) - .customView(R.layout.dialog_address, false) - .onPositive((dialog1, which) -> { - if (binder != null && binder.getBackgroundThread() != null) - binder.stopBackgroundThread(); - - View parent = dialog1.getCustomView(); - assertNotNull(parent); - AppCompatEditText hostField = (AppCompatEditText) parent.findViewById(R.id.host); - AppCompatEditText portField = (AppCompatEditText) parent.findViewById(R.id.port); - String host = hostField.getText().toString().trim(); - int port = Integer.valueOf(portField.getText().toString().trim()); - context.settings().lastHost.set(host); - context.settings().lastPort.set(port); - serviceInterface.connect(new ServerAddress(host, port)); - }) - .negativeColor(context.themeUtil().res.colorForeground) - .positiveText(R.string.labelConnect) - .negativeText(R.string.labelCancel) - .build(); - AppCompatEditText hostField = (AppCompatEditText) dialog.getView().findViewById(R.id.host); - AppCompatEditText portField = (AppCompatEditText) dialog.getView().findViewById(R.id.port); - - hostField.setText(context.settings().lastHost.get()); - portField.setText(String.valueOf(context.settings().lastPort.get())); - - dialog.show(); - } - - public void onEventMainThread(@NonNull BacklogReceivedEvent event) { - if (event.bufferId == status.bufferId) { - swipeView.setRefreshing(false); - } - } - - public void onEventMainThread(@NonNull UnknownCertificateEvent event) { - new MaterialDialog.Builder(this) - .content(context.themeUtil().translations.warningCertificate + "\n" + CertificateUtils.certificateToFingerprint(event.certificate, "")) - .title("Unknown Certificate") - .onPositive((dialog, which) -> { - if (binder != null && binder.getBackgroundThread() != null) { - binder.getBackgroundThread().client().certificateManager.addCertificate(event.certificate, event.address); - } - }) - .negativeColor(context.themeUtil().res.colorForeground) - .positiveText("Yes") - .negativeText("No") - .build() - .show(); - } - - public void onEventMainThread(@NonNull GeneralErrorEvent event) { - assertNotNull(messages); - - Snackbar.make(messages, event.toString(), Snackbar.LENGTH_LONG).show(); - for (String line : Splitter.fixedLength(2048).split(event.toString())) { - Log.e("ChatActivity", line); - } - if (event.exception != null) - event.exception.printStackTrace(); - } - - public void onEventMainThread(LagChangedEvent event) { - updateSubTitle(); - } - - private void updateSubTitle(@Nullable CharSequence text) { - assertNotNull(toolbar); - - if (text != null) { - toolbar.setSubtitle(text); - } else { - toolbar.setSubtitle(""); - } - } - - private static class Status extends Storable { - @Store - int bufferId = -1; - @Store - int bufferViewConfigId = -1; - } - - @PreferenceWrapper(BuildConfig.APPLICATION_ID) - public static abstract class Settings { - @StringPreference("QUASSEL_LIGHT") - String theme; - @BooleanPreference(false) - boolean fullHostmask; - @IntPreference(2) - int textSize; - @BooleanPreference(true) - boolean mircColors; - - @StringPreference("") - String lastHost; - @IntPreference(4242) - int lastPort; - @StringPreference("") - String lastUsername; - @StringPreference("") - String lastPassword; - } - - private class ServiceInterface { - private void connect(@NonNull ServerAddress address) { - assertNotNull(binder); - disconnect(); - - context.setProvider(new BusProvider()); - context.provider().event.register(ChatActivity.this); - binder.startBackgroundThread(context.provider(), address); - onConnectionEstablished(); - } - - private void disconnect() { - if (context.provider() != null) { - context.provider().event.unregister(ChatActivity.this); - } - if (context.client() != null) { - context.client().backlogManager().open(-1); - } - context.setProvider(null); - context.setClient(null); - } - } -} 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 new file mode 100644 index 0000000000000000000000000000000000000000..88bfaa70097c26629499854172bb93cd85fc0921 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java @@ -0,0 +1,183 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.FrameLayout; + +import com.mikepenz.materialdrawer.AccountHeader; +import com.mikepenz.materialdrawer.AccountHeaderBuilder; +import com.mikepenz.materialdrawer.Drawer; + +import aspm.annotations.BooleanPreference; +import aspm.annotations.IntPreference; +import aspm.annotations.PreferenceWrapper; +import aspm.annotations.StringPreference; +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.libquassel.events.ConnectionChangeEvent; +import de.kuschku.libquassel.events.GeneralErrorEvent; +import de.kuschku.quasseldroid_ng.BuildConfig; +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread; +import de.kuschku.quasseldroid_ng.util.BoundActivity; +import de.kuschku.quasseldroid_ng.ui.chat.fragment.ChatFragment; +import de.kuschku.quasseldroid_ng.ui.chat.fragment.LoadingFragment; +import de.kuschku.quasseldroid_ng.ui.chat.util.ActivityImplFactory; +import de.kuschku.quasseldroid_ng.ui.chat.util.ILayoutHelper; +import de.kuschku.quasseldroid_ng.ui.chat.util.Status; +import de.kuschku.quasseldroid_ng.util.accounts.AccountManager; + +import static de.kuschku.util.AndroidAssert.assertNotNull; + +public class MainActivity extends BoundActivity { + + /** + * A helper to handle the different layout implementations + */ + ILayoutHelper layoutHelper; + + /** + * Host layout for content fragment, for example showing a loader or the chat + */ + @Bind(R.id.content_host) + FrameLayout contentHost; + + /** + * Main ActionBar + */ + @Bind(R.id.toolbar) + Toolbar toolbar; + + /** + * The left material drawer of this activity, depending on layout either in the layout hierarchy + * or at the left as pull-out menu + */ + Drawer drawerLeft; + + /** + * AccountHeader field for the bufferviewconfig header + */ + AccountHeader accountHeader; + + /** + * This object encapsulates the current status of the activity – opened bufferview, for example + */ + Status status = new Status(); + + private AccountManager manager; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + ButterKnife.bind(this); + setSupportActionBar(toolbar); + layoutHelper = ActivityImplFactory.of(getResources().getBoolean(R.bool.isTablet), this); + accountHeader = buildAccountHeader(); + drawerLeft = layoutHelper.buildDrawer(savedInstanceState, accountHeader, toolbar); + + replaceFragment(new LoadingFragment()); + + manager = new AccountManager(this); + } + + private void replaceFragment(Fragment fragment) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(R.id.content_host, fragment); + transaction.commit(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + assertNotNull(outState); + + super.onSaveInstanceState(outState); + status.onSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + assertNotNull(savedInstanceState); + + super.onRestoreInstanceState(savedInstanceState); + status.onRestoreInstanceState(savedInstanceState); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.chat, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_hide_events: + return true; + case R.id.action_reauth: + context.settings().lastAccount.set(""); + finish(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private AccountHeader buildAccountHeader() { + return new AccountHeaderBuilder() + .withActivity(this) + .withCompactStyle(true) + .withHeaderBackground(R.drawable.bg1) + .withProfileImagesVisible(false) + .build(); + } + + public void onEventMainThread(ConnectionChangeEvent event) { + if (event.status == ConnectionChangeEvent.Status.CONNECTED) { + replaceFragment(new ChatFragment()); + } + } + + public void onConnectionChange(ConnectionChangeEvent.Status status) { + if (status == ConnectionChangeEvent.Status.CONNECTED) { + replaceFragment(new ChatFragment()); + } + } + + public void onEventMainThread(GeneralErrorEvent event) { + + } + + @Override + protected void onConnectToThread(@Nullable ClientBackgroundThread thread) { + super.onConnectToThread(thread); + if (thread == null) + connectToServer(manager.account(context.settings().lastAccount.get())); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/Settings.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/Settings.java new file mode 100644 index 0000000000000000000000000000000000000000..0d3e09c2bc07764b1c6e02dc1b3fb5f962138edf --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/Settings.java @@ -0,0 +1,62 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat; + +import android.content.Context; +import android.content.SharedPreferences; + +import aspm.BooleanPreference; +import aspm.IntPreference; +import aspm.StringPreference; +import de.kuschku.util.backports.Objects; + +public class Settings { + public final StringPreference lastAccount; + + public final IntPreference textSize; + + public final BooleanPreference mircColors; + + public final BooleanPreference fullHostmask; + + public final StringPreference theme; + + public Settings(SharedPreferences pref) { + this.lastAccount = new StringPreference(pref, "lastAccount", ""); + this.textSize = new IntPreference(pref, "textSize", 2); + this.mircColors = new BooleanPreference(pref, "mircColors", true); + this.fullHostmask = new BooleanPreference(pref, "fullHostmask", false); + this.theme = new StringPreference(pref, "theme", "QUASSEL_LIGHT"); + + pref.registerOnSharedPreferenceChangeListener((preferences, key) -> { + if (Objects.equals(key, "lastAccount")) lastAccount.change(); + if (Objects.equals(key, "textSize")) textSize.change(); + if (Objects.equals(key, "mircColors")) mircColors.change(); + if (Objects.equals(key, "fullHostmask")) fullHostmask.change(); + if (Objects.equals(key, "theme")) theme.change(); + }); + } + + public Settings(Context ctx) { + this(ctx.getSharedPreferences("de.kuschku.quasseldroid_ng", 0)); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NickListWrapper.java similarity index 99% rename from app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java rename to app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NickListWrapper.java index d55c3a6b6aea40ab99efa8733ea6b0e38029db0d..0e55bf39ad65bd26a388e4037b50bd56eec50e57 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NickListWrapper.java @@ -19,7 +19,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -package de.kuschku.quasseldroid_ng.ui.chat; +package de.kuschku.quasseldroid_ng.ui.chat.drawer; import android.support.annotation.NonNull; 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 new file mode 100644 index 0000000000000000000000000000000000000000..3abb53736ea96f60cb88cc9f8ce35a7240c9a32e --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java @@ -0,0 +1,107 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.fragment; + +import android.os.Bundle; +import android.support.annotation.Nullable; +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.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.sothree.slidinguppanel.SlidingUpPanelLayout; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.libquassel.client.Client; +import de.kuschku.libquassel.events.BacklogReceivedEvent; +import de.kuschku.libquassel.events.BufferChangeEvent; +import de.kuschku.libquassel.message.Message; +import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager; +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.util.BoundFragment; +import de.kuschku.quasseldroid_ng.ui.chat.chatview.MessageAdapter; +import de.kuschku.quasseldroid_ng.ui.chat.util.SlidingPanelHandler; +import de.kuschku.util.observables.AutoScroller; +import de.kuschku.util.observables.lists.ObservableComparableSortedList; + +import static de.kuschku.util.AndroidAssert.assertNotNull; + +public class ChatFragment extends BoundFragment { + private SlidingPanelHandler panelHandler; + private MessageAdapter messageAdapter; + + /** + * The list containing the messages to be displayed + */ + @Bind(R.id.messages) + RecyclerView messages; + + @Bind(R.id.swipe_view) + SwipeRefreshLayout swipeView; + + @Bind(R.id.sliding_layout) + SlidingUpPanelLayout sliderMain; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_chat, container, false); + panelHandler = new SlidingPanelHandler(getActivity(), (SlidingUpPanelLayout) view, context); + ButterKnife.bind(this, view); + + assertNotNull(messages); + + messages.setItemAnimator(new DefaultItemAnimator()); + messages.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, true)); + messageAdapter = new MessageAdapter(getActivity(), context, new AutoScroller(messages)); + messages.setAdapter(messageAdapter); + + swipeView.setColorSchemeColors(context.themeUtil().res.colorPrimary); + swipeView.setEnabled(false); + + return view; + } + + public void onEventMainThread(BufferChangeEvent event) { + Client client = context.client(); + if (client != null) { + QBacklogManager<? extends QBacklogManager> backlogManager = client.backlogManager(); + int id = backlogManager.open(); + ObservableComparableSortedList<Message> messageList = backlogManager.filtered(id); + messageAdapter.setMessageList(messageList); + swipeView.setEnabled(id != -1); + } else { + swipeView.setEnabled(false); + } + } + + public void onEventMainThread(BacklogReceivedEvent event) { + Client client = context.client(); + if (client != null && client.backlogManager().open() == event.bufferId) { + swipeView.setRefreshing(false); + } + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..d88b873c305293e3f380e83fcfa418ee61cfe32e --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java @@ -0,0 +1,99 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.fragment; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.libquassel.events.BacklogInitEvent; +import de.kuschku.libquassel.events.ConnectionChangeEvent; +import de.kuschku.libquassel.events.InitEvent; +import de.kuschku.libquassel.primitives.types.BufferInfo; +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.util.BoundFragment; + +import static de.kuschku.util.AndroidAssert.assertNotNull; + +public class LoadingFragment extends BoundFragment { + @Bind(R.id.progressBar) + ProgressBar progressBar; + + @Bind(R.id.label) + TextView label; + + @Bind(R.id.count) + TextView count; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_loading, container, false); + ButterKnife.bind(this, view); + + + label.setText("Connecting"); + count.setText(""); + + return view; + } + + public void onEventMainThread(ConnectionChangeEvent event) { + progressBar.setIndeterminate(true); + + label.setText(event.status.name()); + count.setText(""); + } + + public void onEventMainThread(InitEvent event) { + if (context.client().connectionStatus() == ConnectionChangeEvent.Status.INITIALIZING_DATA) { + progressBar.setIndeterminate(false); + progressBar.setMax(event.max); + progressBar.setProgress(event.loaded); + + label.setText(event.getClass().getSimpleName()); + count.setText(String.format("%d/%d", event.loaded, event.max)); + } + } + + public void onEventMainThread(BacklogInitEvent event) { + if (context.client().connectionStatus() == ConnectionChangeEvent.Status.LOADING_BACKLOG) { + progressBar.setIndeterminate(false); + progressBar.setMax(event.max); + progressBar.setProgress(event.loaded); + + label.setText(event.getClass().getSimpleName()); + count.setText(String.format("%d/%d", event.loaded, event.max)); + } + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ActivityImplFactory.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ActivityImplFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..26e7f29faa8bc8eb6360920fabfaccb40a98c4f1 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ActivityImplFactory.java @@ -0,0 +1,35 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.util; + +import de.kuschku.quasseldroid_ng.ui.chat.MainActivity; + +public class ActivityImplFactory { + private ActivityImplFactory() { + + } + + + public static ILayoutHelper of(boolean tablet, MainActivity activity) { + return (tablet) ? new LayoutHelperTabletImpl(activity) : new LayoutHelperPhoneImpl(activity); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ILayoutHelper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ILayoutHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..feb4315807186c7ec1e82e0c3e3809c5a86ba615 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ILayoutHelper.java @@ -0,0 +1,33 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.util; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.Toolbar; + +import com.mikepenz.materialdrawer.AccountHeader; +import com.mikepenz.materialdrawer.Drawer; + +public interface ILayoutHelper { + Drawer buildDrawer(@Nullable Bundle savedInstanceState, AccountHeader accountHeader, Toolbar toolbar); +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperPhoneImpl.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperPhoneImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..a8b7775705a3ab4ccfea36ca913237376753d581 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperPhoneImpl.java @@ -0,0 +1,50 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.util; + +import android.os.Bundle; +import android.support.v7.widget.Toolbar; + +import com.mikepenz.materialdrawer.AccountHeader; +import com.mikepenz.materialdrawer.Drawer; +import com.mikepenz.materialdrawer.DrawerBuilder; + +import de.kuschku.quasseldroid_ng.ui.chat.MainActivity; + +public class LayoutHelperPhoneImpl implements ILayoutHelper { + private final MainActivity activity; + + public LayoutHelperPhoneImpl(MainActivity activity) { + this.activity = activity; + } + + @Override + public Drawer buildDrawer(Bundle savedInstanceState, AccountHeader accountHeader, Toolbar toolbar) { + return new DrawerBuilder() + .withActivity(activity) + .withToolbar(toolbar) + .withAccountHeader(accountHeader) + .withTranslucentStatusBar(true) + .withSavedInstance(savedInstanceState) + .build(); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperTabletImpl.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperTabletImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..3ced622bc146ff0cb6ee64abe4f81c568d693cfe --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperTabletImpl.java @@ -0,0 +1,55 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.util; + +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.widget.FrameLayout; + +import com.mikepenz.materialdrawer.AccountHeader; +import com.mikepenz.materialdrawer.Drawer; +import com.mikepenz.materialdrawer.DrawerBuilder; + +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.ui.chat.MainActivity; + +public class LayoutHelperTabletImpl implements ILayoutHelper { + private final MainActivity activity; + + public LayoutHelperTabletImpl(MainActivity activity) { + this.activity = activity; + } + + @Override + public Drawer buildDrawer(Bundle savedInstanceState, AccountHeader accountHeader, Toolbar toolbar) { + Drawer drawer = new DrawerBuilder() + .withActivity(activity) + .withToolbar(toolbar) + .withAccountHeader(accountHeader) + .withTranslucentStatusBar(false) + .withSavedInstance(savedInstanceState) + .buildView(); + FrameLayout drawerHost = (FrameLayout) activity.findViewById(R.id.drawer_host); + drawerHost.addView(drawer.getSlider()); + return drawer; + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ServiceHelper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ServiceHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..3b810f20fa23fcfa8f8fd2b3dd349659ed27f8a3 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ServiceHelper.java @@ -0,0 +1,76 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.util; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; + +import de.kuschku.quasseldroid_ng.service.QuasselService; +import de.kuschku.quasseldroid_ng.ui.chat.Settings; +import de.kuschku.quasseldroid_ng.ui.theme.AppContext; +import de.kuschku.quasseldroid_ng.ui.theme.AppTheme; +import de.kuschku.quasseldroid_ng.ui.theme.ThemeUtil; + +public class ServiceHelper { + private ServiceHelper() { + } + + /** + * Connects to an already running QuasselService + * @param context The context in which the service is running + * @param connection The connection to which it should be bound + */ + public static void connectToService(Context context, ServiceConnection connection) { + Intent intent = new Intent(context, QuasselService.class); + context.bindService(intent, connection, Context.BIND_IMPORTANT); + } + + /** + * Connects to an already running QuasselService + * @param context The context in which the service is running + * @param connection The connection which should be disconnected + */ + public static void disconnect(Context context, ServiceConnection connection) { + context.unbindService(connection); + } + + /** + * Starts a new QuasselService, if not yet running. + * @param context The context in which it should run + */ + public static void startServiceIfNotRunning(Context context) { + Intent intent = new Intent(context, QuasselService.class); + context.startService(intent); + } + + public static void initTheme(AppContext context, Activity activity) { + // Init SharedPreferences + Settings settings = new Settings(activity); + context.setSettings(settings); + // Load Theme from Preferences + AppTheme theme = AppTheme.themeFromString(settings.theme.get()); + activity.setTheme(theme.themeId); + context.setThemeUtil(new ThemeUtil(activity, theme)); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..3f02e84a2f00ebffea4d6b1af393310b66fd5976 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java @@ -0,0 +1,211 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.util; + +import android.app.Activity; +import android.support.v7.widget.ActionMenuView; +import android.support.v7.widget.AppCompatEditText; +import android.support.v7.widget.AppCompatImageButton; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; + +import com.mikepenz.fastadapter.FastAdapter; +import com.mikepenz.fastadapter.IItem; +import com.mikepenz.fastadapter.adapters.ItemAdapter; +import com.mikepenz.materialdrawer.model.PrimaryDrawerItem; +import com.sothree.slidinguppanel.SlidingUpPanelLayout; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.ui.editor.AdvancedEditor; +import de.kuschku.quasseldroid_ng.ui.theme.AppContext; +import de.kuschku.quasseldroid_ng.ui.theme.ThemeUtil; + +import static de.kuschku.util.AndroidAssert.assertNotNull; + +public class SlidingPanelHandler { + private final Activity activity; + private final AppContext context; + private final AdvancedEditor editor; + + // Main Sliding Layout + SlidingUpPanelLayout slidingLayout; + + // Input History + @Bind(R.id.sliding_layout_history) + SlidingUpPanelLayout slidingLayoutHistory; + @Bind(R.id.msg_history) + RecyclerView msgHistory; + + // Advanced Formatter + @Bind(R.id.formatting_menu) + ActionMenuView formattingMenu; + @Bind(R.id.formatting_toolbar) + Toolbar formattingToolbar; + + // Input Line + @Bind(R.id.chatline) + AppCompatEditText chatline; + @Bind(R.id.send) + AppCompatImageButton send; + + public SlidingPanelHandler(Activity activity, SlidingUpPanelLayout slidingLayout, AppContext context) { + this.slidingLayout = slidingLayout; + ButterKnife.bind(this, slidingLayout); + this.activity = activity; + this.context = context; + this.editor = new AdvancedEditor(context, chatline); + + setupFormattingMenu(activity); + + setupHistoryFakeData(); + + bindListener(); + } + + private void setupFormattingMenu(Activity activity) { + activity.getMenuInflater().inflate(R.menu.formatting, formattingMenu.getMenu()); + formattingMenu.setOnMenuItemClickListener(item -> { + switch (item.getItemId()) { + case R.id.format_bold: + editor.toggleBold(); + return true; + case R.id.format_italic: + editor.toggleItalic(); + return true; + case R.id.format_underline: + editor.toggleUnderline(); + return true; + case R.id.action_history: + openHistory(); + return true; + default: + return false; + } + }); + } + + public void setFormattingEnabled(boolean formattingEnabled) { + Menu menu = formattingMenu.getMenu(); + MenuItem[] items = new MenuItem[]{ + menu.findItem(R.id.format_bold), + menu.findItem(R.id.format_italic), + menu.findItem(R.id.format_underline), + menu.findItem(R.id.format_paint), + menu.findItem(R.id.format_fill) + }; + + for (MenuItem item : items) { + if (item != null) + item.setEnabled(!formattingEnabled); + } + } + + private void setChatlineExpanded(boolean expanded) { + assertNotNull(chatline); + assertNotNull(chatline.getLayoutParams()); + + ThemeUtil themeUtil = context.themeUtil(); + assertNotNull(themeUtil); + + int selectionStart = chatline.getSelectionStart(); + int selectionEnd = chatline.getSelectionEnd(); + + if (expanded) { + chatline.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; + } else { + chatline.getLayoutParams().height = themeUtil.res.actionBarSize; + } + chatline.setSingleLine(!expanded); + + chatline.setSelection(selectionStart, selectionEnd); + } + + private void bindListener() { + slidingLayout.setAntiDragView(R.id.card_panel); + slidingLayout.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() { + @Override + public void onPanelSlide(View panel, float slideOffset) { + + } + + @Override + public void onPanelCollapsed(View panel) { + setChatlineExpanded(false); + } + + @Override + public void onPanelExpanded(View panel) { + setChatlineExpanded(true); + } + + @Override + public void onPanelAnchored(View panel) { + + } + + @Override + public void onPanelHidden(View panel) { + + } + }); + setChatlineExpanded(slidingLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED); + } + + 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") + ); + msgHistory.setAdapter(fastAdapter); + msgHistory.setLayoutManager(new LinearLayoutManager(activity)); + msgHistory.setItemAnimator(new DefaultItemAnimator()); + } + + private void openHistory() { + slidingLayoutHistory.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/Status.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/Status.java new file mode 100644 index 0000000000000000000000000000000000000000..15eb3f9b3e553c3c3e7ec65229e0d04e758fbcd1 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/Status.java @@ -0,0 +1,30 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.chat.util; + +import de.kuschku.util.instancestateutil.Storable; +import de.kuschku.util.instancestateutil.Store; + +public class Status extends Storable { + @Store + int bufferViewConfigId = -1; +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountItem.java new file mode 100644 index 0000000000000000000000000000000000000000..2be3d7ecfa55649e0b8ee514031fcb1dc63cb0b6 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountItem.java @@ -0,0 +1,163 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.support.annotation.ColorInt; +import android.support.v7.widget.AppCompatRadioButton; +import android.support.v7.widget.RecyclerView; +import android.util.Pair; +import android.view.View; +import android.widget.TextView; + +import com.mikepenz.fastadapter.utils.ViewHolderFactory; +import com.mikepenz.materialdrawer.model.AbstractDrawerItem; +import com.mikepenz.materialdrawer.util.DrawerUIUtils; + +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.util.accounts.Account; + +public class AccountItem extends AbstractDrawerItem<AccountItem, AccountItem.ViewHolder> { + public final Account account; + + public AccountItem(Account account) { + this.account = account; + } + + @Override + public int getType() { + return R.id.item_account; + } + + @Override + public int getLayoutRes() { + return R.layout.widget_core_account; + } + + @Override + public boolean isSelectable() { + return true; + } + + @Override + public void bindView(ViewHolder viewHolder) { + Context ctx = viewHolder.itemView.getContext(); + + //set the identifier from the drawerItem here. It can be used to run tests + viewHolder.itemView.setId(hashCode()); + + //set the item selected if it is + viewHolder.itemView.setSelected(isSelected()); + + //get the correct color for the text + int color = getColor(ctx); + int selectedTextColor = getSelectedTextColor(ctx); + + viewHolder.name.setText(account.name); + + viewHolder.select.setChecked(isSelected()); + viewHolder.select.setClickable(false); + + viewHolder.description.setText(viewHolder.itemView.getContext().getString(R.string.labelUserOnHost, account.user, account.host)); + + viewHolder.name.setTextColor(getTextColorStateList(color, selectedTextColor)); + + viewHolder.description.setTextColor(getTextColorStateList(color, selectedTextColor)); + + //for android API 17 --> Padding not applied via xml + DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view); + + //call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required) + onPostBindView(this, viewHolder.itemView); + } + + @Override + public ViewHolderFactory getFactory() { + return new ItemFactory(); + } + + public static class ItemFactory implements ViewHolderFactory<ViewHolder> { + public ViewHolder create(View v) { + return new ViewHolder(v); + } + } + + protected static class ViewHolder extends RecyclerView.ViewHolder { + private View view; + private AppCompatRadioButton select; + private TextView name; + private TextView description; + + private ViewHolder(View view) { + super(view); + this.view = view; + this.select = (AppCompatRadioButton) view.findViewById(R.id.account_select); + this.name = (TextView) view.findViewById(R.id.account_name); + this.description = (TextView) view.findViewById(R.id.account_description); + } + } + + + /** + * helper method to decide for the correct color + * + * @param ctx + * @return + */ + protected int getColor(Context ctx) { + int color; + if (this.isEnabled()) { + color = com.mikepenz.materialdrawer.R.color.material_drawer_primary_text; + } else { + color = com.mikepenz.materialdrawer.R.color.material_drawer_hint_text; + } + return color; + } + + /** + * helper method to decide for the correct color + * + * @param ctx + * @return + */ + protected int getSelectedTextColor(Context ctx) { + return com.mikepenz.materialdrawer.R.color.material_drawer_selected_text; + } + + protected Pair<Integer, ColorStateList> colorStateList; + + /** + * helper to get the ColorStateList for the text and remembering it so we do not have to recreate it all the time + * + * @param color + * @param selectedTextColor + * @return + */ + protected ColorStateList getTextColorStateList(@ColorInt int color, @ColorInt int selectedTextColor) { + if (colorStateList == null || color + selectedTextColor != colorStateList.first) { + colorStateList = new Pair<>(color + selectedTextColor, DrawerUIUtils.getTextColorStateList(color, selectedTextColor)); + } + + return colorStateList.second; + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSelectActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSelectActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..bba27567a72d9a40261c387086606df9fd3794be --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSelectActivity.java @@ -0,0 +1,94 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSelectSlide; +import de.kuschku.quasseldroid_ng.ui.setup.slides.SlideFragment; + +public class AccountSelectActivity extends AppCompatActivity { + private SlidePagerAdapter slidePagerAdapter; + + @Bind(R.id.view_pager) + ViewPager viewPager; + + @Bind(R.id.btn) + FloatingActionButton btn; + + private class SlidePagerAdapter extends FragmentPagerAdapter { + private SlideFragment item = new AccountSelectSlide(); + + public SlidePagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public SlideFragment getItem(int position) { + return item; + } + + @Override + public int getCount() { + return 1; + } + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_setup); + ButterKnife.bind(this); + slidePagerAdapter = new SlidePagerAdapter(getSupportFragmentManager()); + + viewPager.setAdapter(slidePagerAdapter); + slidePagerAdapter.notifyDataSetChanged(); + updateValidity(slidePagerAdapter.item.isValid()); + btn.setImageResource(R.drawable.ic_check_dark); + slidePagerAdapter.item.addChangeListener(this::updateValidity); + btn.setOnClickListener(v -> { + Bundle bundle = new Bundle(); + slidePagerAdapter.item.getData(bundle); + + Intent result = new Intent(); + result.putExtra("extra", bundle); + setResult(RESULT_OK, result); + finish(); + }); + } + + public void updateValidity(boolean validity) { + btn.setVisibility(validity ? View.VISIBLE : View.GONE); + slidePagerAdapter.notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSetupActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSetupActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..f424544ba01825d4f28e61b1eef8561f4f4532d1 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSetupActivity.java @@ -0,0 +1,172 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupCoreSlide; +import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupNameSlide; +import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupUserSlide; +import de.kuschku.quasseldroid_ng.ui.setup.slides.SlideFragment; +import de.kuschku.quasseldroid_ng.util.accounts.Account; +import de.kuschku.quasseldroid_ng.util.accounts.AccountManager; + +public class AccountSetupActivity extends AppCompatActivity implements ValidUpdateCallback { + + private SlidePagerAdapter slidePagerAdapter; + + @Bind(R.id.view_pager) + ViewPager viewPager; + + @Bind(R.id.btn) + FloatingActionButton btn; + + private int lastValidPage = -1; + + private class SlidePagerAdapter extends FragmentPagerAdapter { + List<SlideFragment> list = new ArrayList<>(); + + public SlidePagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public SlideFragment getItem(int position) { + return list.get(position); + } + + @Override + public int getCount() { + return Math.min(lastValidPage + 2, list.size()); + } + + public void addFragment(SlideFragment fragment) { + list.add(fragment); + notifyDataSetChanged(); + } + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_setup); + ButterKnife.bind(this); + + slidePagerAdapter = new SlidePagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(slidePagerAdapter); + + slidePagerAdapter.addFragment(new AccountSetupCoreSlide()); + slidePagerAdapter.addFragment(new AccountSetupUserSlide()); + slidePagerAdapter.addFragment(new AccountSetupNameSlide()); + + SlideFragment item = slidePagerAdapter.getItem(viewPager.getCurrentItem()); + + updateValidity(item.isValid()); + + btn.setOnClickListener(v -> { + if (viewPager.getCurrentItem() == slidePagerAdapter.getCount() - 1) { + onDone(); + } else { + viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true); + } + }); + + slidePagerAdapter.getItem(viewPager.getCurrentItem()).addChangeListener(AccountSetupActivity.this); + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + SlideFragment slideFragment = slidePagerAdapter.getItem(viewPager.getCurrentItem()); + for (int i = 0; i < slidePagerAdapter.getCount(); i++) { + slidePagerAdapter.getItem(i).removeChangeListener(AccountSetupActivity.this); + } + slideFragment.addChangeListener(AccountSetupActivity.this); + updateValidity(slideFragment.isValid()); + if (viewPager.getCurrentItem() == slidePagerAdapter.list.size() - 1) { + btn.setImageResource(R.drawable.ic_check_dark); + } else { + btn.setImageResource(R.drawable.ic_arrow_right_dark); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + } + + private void onDone() { + Bundle bundle = new Bundle(); + for (SlideFragment fragment : slidePagerAdapter.list) { + fragment.getData(bundle); + } + + setupAccount(bundle); + + Intent result = new Intent(); + result.putExtra("extra", bundle); + setResult(RESULT_OK, result); + finish(); + } + + private void setupAccount(Bundle bundle) { + AccountManager manager = new AccountManager(this); + manager.add(new Account( + UUID.randomUUID(), + bundle.getString("name"), + bundle.getString("host"), + bundle.getInt("port"), + bundle.getString("user"), + bundle.getString("pass") + )); + } + + public void updateValidity(boolean validity) { + btn.setVisibility(validity ? View.VISIBLE : View.GONE); + if (validity) { + lastValidPage = viewPager.getCurrentItem(); + } else { + lastValidPage = viewPager.getCurrentItem() - 1; + } + slidePagerAdapter.notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CreateAccountItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CreateAccountItem.java new file mode 100644 index 0000000000000000000000000000000000000000..550abdb3dc05f78a72bb1040cefbd63b1e4bc900 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CreateAccountItem.java @@ -0,0 +1,129 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.support.annotation.ColorInt; +import android.support.v7.widget.AppCompatRadioButton; +import android.support.v7.widget.RecyclerView; +import android.util.Pair; +import android.view.View; +import android.widget.TextView; + +import com.mikepenz.fastadapter.utils.ViewHolderFactory; +import com.mikepenz.materialdrawer.model.AbstractDrawerItem; +import com.mikepenz.materialdrawer.util.DrawerUIUtils; + +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.util.accounts.Account; + +public class CreateAccountItem extends AbstractDrawerItem<CreateAccountItem, CreateAccountItem.ViewHolder> { + @Override + public int getType() { + return R.id.item_create_account; + } + + @Override + public int getLayoutRes() { + return R.layout.widget_core_account_add; + } + + @Override + public void bindView(ViewHolder viewHolder) { + //set the identifier from the drawerItem here. It can be used to run tests + viewHolder.itemView.setId(hashCode()); + + //set the item selected if it is + viewHolder.itemView.setSelected(isSelected()); + + //for android API 17 --> Padding not applied via xml + DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view); + + //call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required) + onPostBindView(this, viewHolder.itemView); + } + + @Override + public ViewHolderFactory getFactory() { + return new ItemFactory(); + } + + public static class ItemFactory implements ViewHolderFactory<ViewHolder> { + public ViewHolder create(View v) { + return new ViewHolder(v); + } + } + + protected static class ViewHolder extends RecyclerView.ViewHolder { + private View view; + + private ViewHolder(View view) { + super(view); + this.view = view; + } + } + + + /** + * helper method to decide for the correct color + * + * @param ctx + * @return + */ + protected int getColor(Context ctx) { + int color; + if (this.isEnabled()) { + color = com.mikepenz.materialdrawer.R.color.material_drawer_primary_text; + } else { + color = com.mikepenz.materialdrawer.R.color.material_drawer_hint_text; + } + return color; + } + + /** + * helper method to decide for the correct color + * + * @param ctx + * @return + */ + protected int getSelectedTextColor(Context ctx) { + return com.mikepenz.materialdrawer.R.color.material_drawer_selected_text; + } + + protected Pair<Integer, ColorStateList> colorStateList; + + /** + * helper to get the ColorStateList for the text and remembering it so we do not have to recreate it all the time + * + * @param color + * @param selectedTextColor + * @return + */ + protected ColorStateList getTextColorStateList(@ColorInt int color, @ColorInt int selectedTextColor) { + if (colorStateList == null || color + selectedTextColor != colorStateList.first) { + colorStateList = new Pair<>(color + selectedTextColor, DrawerUIUtils.getTextColorStateList(color, selectedTextColor)); + } + + return colorStateList.second; + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/ValidUpdateCallback.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/ValidUpdateCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..05328f0858f0f727ceb165c67ec8b9d9bebcc9ff --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/ValidUpdateCallback.java @@ -0,0 +1,26 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup; + +public interface ValidUpdateCallback { + void updateValidity(boolean isValid); +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSelectSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSelectSlide.java new file mode 100644 index 0000000000000000000000000000000000000000..68947dc15cee466415631ae1dea1c00f84addd77 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSelectSlide.java @@ -0,0 +1,148 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup.slides; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.mikepenz.fastadapter.FastAdapter; +import com.mikepenz.fastadapter.IItem; +import com.mikepenz.fastadapter.adapters.ItemAdapter; + +import java.util.Iterator; +import java.util.Set; + +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.ui.setup.AccountItem; +import de.kuschku.quasseldroid_ng.ui.setup.AccountSetupActivity; +import de.kuschku.quasseldroid_ng.ui.setup.CreateAccountItem; +import de.kuschku.quasseldroid_ng.util.accounts.Account; +import de.kuschku.quasseldroid_ng.util.accounts.AccountManager; +import de.kuschku.util.backports.Optional; +import de.kuschku.util.backports.Optionals; + +public class AccountSelectSlide extends SlideFragment { + private ItemAdapter<IItem> itemAdapter; + private FastAdapter<IItem> fastAdapter; + private AccountManager manager; + + @Override + public Bundle getData(Bundle in) { + AccountItem item = (AccountItem) findAny(fastAdapter.getSelectedItems()).get(); + in.putString("account", item.account.id.toString()); + return in; + } + + private <T> Optional<T> findAny(Set<T> selections) { + Iterator<T> iterator = selections.iterator(); + if (iterator.hasNext()) { + return Optionals.of(iterator.next()); + } else { + return Optionals.absent(); + } + } + + @Override + public boolean isValid() { + return fastAdapter != null && fastAdapter.getSelections().size() == 1 && findAny(fastAdapter.getSelectedItems()).get() instanceof AccountItem; + } + + @Override + protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) { + RecyclerView recyclerView = (RecyclerView) inflater.inflate(R.layout.slide_select, container, false); + + manager = new AccountManager(getContext()); + + fastAdapter = new FastAdapter<>(); + itemAdapter = new ItemAdapter<>(); + itemAdapter.wrap(fastAdapter); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.setItemAnimator(new DefaultItemAnimator()); + updateContent(true); + recyclerView.setAdapter(fastAdapter); + + fastAdapter.withSelectWithItemUpdate(true); + fastAdapter.withOnClickListener((v, adapter, item, position) -> { + if (item instanceof CreateAccountItem) { + createNew(); + return true; + } else { + fastAdapter.deselect(); + fastAdapter.select(position); + updateValidity(); + return false; + } + }); + + + return recyclerView; + } + + private void createNew() { + Intent intent = new Intent(getContext(), AccountSetupActivity.class); + startActivityForResult(intent, 0); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (findAny(fastAdapter.getSelectedItems()).get() instanceof CreateAccountItem) + fastAdapter.deselect(); + + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == Activity.RESULT_OK) { + updateContent(false); + } else if (fastAdapter.getItemCount() == 0) { + getActivity().finish(); + } + } + + private void updateContent(boolean autoCreate) { + itemAdapter.clear(); + Set<Account> accounts = manager.accounts(); + for (Account account : accounts) { + itemAdapter.add(new AccountItem(account)); + } + itemAdapter.add(new CreateAccountItem()); + + if (accounts.size() == 0) { + createNew(); + } + } + + @Override + protected int getTitle() { + return R.string.slideAccountselectTitle; + } + + @Override + protected int getDescription() { + return R.string.slideAccountselectDescription; + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java new file mode 100644 index 0000000000000000000000000000000000000000..92745729bcf43fd5f9347006980f769c91028ff0 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java @@ -0,0 +1,118 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup.slides; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v7.widget.AppCompatEditText; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.quasseldroid_ng.R; + +public class AccountSetupCoreSlide extends SlideFragment { + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Bind(R.id.host) + AppCompatEditText hostField; + + @Bind(R.id.port) + AppCompatEditText portField; + + @Override + protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.slide_account_core, container, false); + ButterKnife.bind(this, view); + hostField.addTextChangedListener(watcher); + portField.addTextChangedListener(watcher); + return view; + } + + @Override + public Bundle getData(Bundle in) { + in.putString("host", hostField.getText().toString()); + in.putInt("port", Integer.valueOf(portField.getText().toString())); + return in; + } + + @Override + public boolean isValid() { + return validHost() && validPort(); + } + + @Override + @StringRes + public int getTitle() { + return R.string.slideAccountcoreTitle; + } + + @Override + @StringRes + public int getDescription() { + return R.string.slideAccountcoreDescription; + } + + private boolean validPort() { + if (portField == null) + return false; + + String portText = portField.getText().toString(); + try { + int port = Integer.parseInt(portText); + return port <= 65536 && port > 0; + } catch (NumberFormatException e) { + return false; + } + } + + private boolean validHost() { + if (hostField == null) + return false; + + String hostText = hostField.getText().toString(); + return !hostText.isEmpty(); + } + + TextWatcher watcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + updateValidity(); + } + + @Override + public void afterTextChanged(Editable s) { + } + }; +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java new file mode 100644 index 0000000000000000000000000000000000000000..b50ae81d6527da31afaabe2c448c1fc7e9149f9f --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java @@ -0,0 +1,100 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup.slides; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v7.widget.AppCompatEditText; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.quasseldroid_ng.R; + +public class AccountSetupNameSlide extends SlideFragment { + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Bind(R.id.name) + AppCompatEditText nameField; + + @Override + protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.slide_account_name, container, false); + ButterKnife.bind(this, view); + nameField.addTextChangedListener(watcher); + return view; + } + + @Override + public Bundle getData(Bundle in) { + in.putString("name", nameField.getText().toString()); + return in; + } + + @Override + public boolean isValid() { + return validName(); + } + + @Override + @StringRes + public int getTitle() { + return R.string.slideAccountnameTitle; + } + + @Override + @StringRes + public int getDescription() { + return R.string.slideAccountnameDescription; + } + + private boolean validName() { + if (nameField == null) + return false; + + String hostText = nameField.getText().toString(); + return !hostText.isEmpty(); + } + + TextWatcher watcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + updateValidity(); + } + + @Override + public void afterTextChanged(Editable s) { + } + }; +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java new file mode 100644 index 0000000000000000000000000000000000000000..c6b77f179eda08de4b5ceba3a827dccdda8b5e89 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java @@ -0,0 +1,113 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup.slides; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v7.widget.AppCompatEditText; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import butterknife.Bind; +import butterknife.ButterKnife; +import de.kuschku.quasseldroid_ng.R; + +public class AccountSetupUserSlide extends SlideFragment { + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Bind(R.id.user) + AppCompatEditText userField; + + @Bind(R.id.pass) + AppCompatEditText passField; + + @Override + public View onCreateContent(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.slide_account_user, container, false); + ButterKnife.bind(this, view); + userField.addTextChangedListener(watcher); + passField.addTextChangedListener(watcher); + return view; + } + + @Override + public Bundle getData(Bundle in) { + in.putString("user", userField.getText().toString()); + in.putString("pass", passField.getText().toString()); + return in; + } + + @Override + public boolean isValid() { + return validUser() && validPass(); + } + + @Override + @StringRes + public int getTitle() { + return R.string.slideAccountuserTitle; + } + + @Override + @StringRes + public int getDescription() { + return R.string.slideAccountuserDescription; + } + + private boolean validUser() { + if (userField == null) + return false; + + String hostText = userField.getText().toString(); + return !hostText.isEmpty(); + } + + private boolean validPass() { + if (passField == null) + return false; + + String hostText = passField.getText().toString(); + return !hostText.isEmpty(); + } + + TextWatcher watcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + updateValidity(); + } + }; +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..a0f460dc66bcdce5adc30a669e31a46c1b1aff70 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java @@ -0,0 +1,80 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.ui.setup.slides; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.HashSet; +import java.util.Set; + +import de.kuschku.quasseldroid_ng.R; +import de.kuschku.quasseldroid_ng.ui.setup.ValidUpdateCallback; + +public abstract class SlideFragment extends Fragment { + private Set<ValidUpdateCallback> callbacks = new HashSet<>(); + + public abstract Bundle getData(Bundle in); + + + public abstract boolean isValid(); + public void addChangeListener(ValidUpdateCallback callback) { + callbacks.add(callback); + } + public void removeChangeListener(ValidUpdateCallback callback) { + callbacks.remove(callback); + } + protected void updateValidity() { + updateValidity(isValid()); + } + protected void updateValidity(boolean validity) { + for (ValidUpdateCallback callback : callbacks) { + callback.updateValidity(validity); + } + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.slide, container, false); + ViewGroup viewGroup = (ViewGroup) view.findViewById(R.id.content_host); + viewGroup.addView(onCreateContent(inflater, viewGroup, savedInstanceState)); + + ((TextView) view.findViewById(R.id.title)).setText(getTitle()); + ((TextView) view.findViewById(R.id.description)).setText(getDescription()); + + return view; + } + protected abstract View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState); + + @StringRes + protected abstract int getTitle(); + + @StringRes + protected abstract int getDescription(); +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java index 1ff313ca85c30483000c2f234893802f6a99a5a0..3ccec30be24c1207e20aa7c4d809eb0dbde20bc9 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java @@ -25,11 +25,11 @@ import android.support.annotation.NonNull; import de.kuschku.libquassel.BusProvider; import de.kuschku.libquassel.client.Client; -import de.kuschku.quasseldroid_ng.ui.chat.WrappedSettings; +import de.kuschku.quasseldroid_ng.ui.chat.Settings; public class AppContext { private ThemeUtil themeUtil; - private WrappedSettings settings; + private Settings settings; private Client client; private BusProvider provider; @@ -47,16 +47,16 @@ public class AppContext { return this; } - public WrappedSettings settings() { + public Settings settings() { return settings; } - public void setSettings(WrappedSettings settings) { + public void setSettings(Settings settings) { this.settings = settings; } @NonNull - public AppContext withSettings(WrappedSettings settings) { + public AppContext withSettings(Settings settings) { setSettings(settings); return this; } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java index fc645268fee9d2e412828d1a47677bb02299faa1..033e43242990fa180f396a862e5998b4b5aa18c0 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java @@ -31,7 +31,8 @@ public enum AppTheme { QUASSEL_LIGHT(R.style.Quassel_Light), QUASSEL_DARK(R.style.Quassel_Dark), MATERIAL_DARK(R.style.Material_Dark), - MATERIAL_LIGHT(R.style.Material_Light); + MATERIAL_LIGHT(R.style.Material_Light), + SOLARIZED_DARK(R.style.Solarized_Dark); public final int themeId; @@ -53,6 +54,8 @@ public enum AppTheme { return MATERIAL_LIGHT; case "QUASSEL_DARK": return QUASSEL_DARK; + case "SOLARIZED_DARK": + return SOLARIZED_DARK; default: case "QUASSEL_LIGHT": 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 d9ff61586e787b43e451c7daa01c0c5209ac9515..32b44f69ac1d39aae7d4ea86ba4758e1ea82864c 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 @@ -216,7 +216,7 @@ public class ThemeUtil { @ColorInt public int colorAccent; - @AutoColor(R.attr.colorAccentFocus) + @AutoColor(R.attr.colorControlHighlight) @ColorInt public int colorAccentFocus; diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..5255927c1bc17bee418bffd610c9f87e92ae7268 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundActivity.java @@ -0,0 +1,105 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.util; + +import android.content.ComponentName; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; + +import de.kuschku.libquassel.BusProvider; +import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread; +import de.kuschku.quasseldroid_ng.service.QuasselService; +import de.kuschku.quasseldroid_ng.ui.chat.Settings; +import de.kuschku.quasseldroid_ng.ui.chat.util.ServiceHelper; +import de.kuschku.quasseldroid_ng.ui.theme.AppContext; +import de.kuschku.quasseldroid_ng.util.accounts.Account; + +public abstract class BoundActivity extends AppCompatActivity { + private QuasselService.LocalBinder binder; + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + if (service instanceof QuasselService.LocalBinder) { + binder = (QuasselService.LocalBinder) service; + binder.addCallback(BoundActivity.this::onConnectToThread); + onConnectToThread(binder.getBackgroundThread()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + binder = null; + onConnectToThread(null); + } + }; + + protected AppContext context = new AppContext(); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + ServiceHelper.initTheme(context, this); + context.withSettings(new Settings(this)); + context.settings().theme.addChangeListener(s -> recreate()); + super.onCreate(savedInstanceState); + ServiceHelper.startServiceIfNotRunning(this); + } + + @Override + protected void onResume() { + super.onResume(); + ServiceHelper.connectToService(this, connection); + } + + @Override + protected void onPause() { + super.onPause(); + ServiceHelper.disconnect(this, connection); + } + + protected void connectToServer(Account account) { + BusProvider provider = new BusProvider(); + binder.startBackgroundThread(provider, account.toAddress()); + } + + protected void onConnectToThread(@Nullable ClientBackgroundThread thread) { + if (thread == null) { + context.withClient(null); + setProvider(null); + } else { + context.withClient(thread.client().client); + setProvider(thread.client().provider); + } + } + + protected void setProvider(BusProvider provider) { + BusProvider oldProvider = context.provider(); + if (oldProvider != null) + oldProvider.event.unregister(this); + if (provider != null) + provider.event.registerSticky(this); + context.withProvider(provider); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..bfa02e762cfebc1746ed2c996cd050549acb675a --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundFragment.java @@ -0,0 +1,104 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.util; + +import android.content.ComponentName; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; + +import de.kuschku.libquassel.BusProvider; +import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread; +import de.kuschku.quasseldroid_ng.service.QuasselService; +import de.kuschku.quasseldroid_ng.ui.chat.Settings; +import de.kuschku.quasseldroid_ng.ui.chat.util.ServiceHelper; +import de.kuschku.quasseldroid_ng.ui.theme.AppContext; +import de.kuschku.quasseldroid_ng.util.accounts.Account; + +public abstract class BoundFragment extends Fragment { + private QuasselService.LocalBinder binder; + + private ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + if (service instanceof QuasselService.LocalBinder) { + binder = (QuasselService.LocalBinder) service; + binder.addCallback(BoundFragment.this::onConnectToThread); + onConnectToThread(binder.getBackgroundThread()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + binder = null; + onConnectToThread(null); + } + }; + + protected AppContext context = new AppContext(); + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + ServiceHelper.initTheme(context, getActivity()); + context.withSettings(new Settings(getActivity())); + super.onCreate(savedInstanceState); + ServiceHelper.startServiceIfNotRunning(getContext()); + } + + @Override + public void onResume() { + super.onResume(); + ServiceHelper.connectToService(getContext(), connection); + } + + @Override + public void onPause() { + super.onPause(); + ServiceHelper.disconnect(getContext(), connection); + } + + protected void connectToServer(Account account) { + BusProvider provider = new BusProvider(); + binder.startBackgroundThread(provider, account.toAddress()); + } + + protected void onConnectToThread(@Nullable ClientBackgroundThread thread) { + if (thread == null) { + context.withClient(null); + setProvider(null); + } else { + context.withClient(thread.client().client); + setProvider(thread.client().provider); + } + } + + protected void setProvider(BusProvider provider) { + BusProvider oldProvider = context.provider(); + if (oldProvider != null) + oldProvider.event.unregister(this); + if (provider != null) + provider.event.registerSticky(this); + context.withProvider(provider); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/Account.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/Account.java new file mode 100644 index 0000000000000000000000000000000000000000..85601c9b8053d64f8f2345c8e0f4c8eb2c40ad86 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/Account.java @@ -0,0 +1,51 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.util.accounts; + +import java.util.UUID; + +import de.kuschku.util.ServerAddress; + +public class Account { + public final UUID id; + + public final String name; + + public final String host; + public final int port; + + public final String user; + public final String pass; + + public Account(UUID id, String name, String host, int port, String user, String pass) { + this.id = id; + this.name = name; + this.host = host; + this.port = port; + this.user = user; + this.pass = pass; + } + + public ServerAddress toAddress() { + return new ServerAddress(host, port); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManager.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManager.java new file mode 100644 index 0000000000000000000000000000000000000000..5aa436af0651bf6febc984c2ab65ef1878d37baf --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManager.java @@ -0,0 +1,61 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.util.accounts; + +import android.content.Context; + +import java.util.Set; +import java.util.UUID; + +import aspm.StringPreference; + +public class AccountManager { + AccountManagerHelper helper; + + public AccountManager(Context context) { + helper = new AccountManagerHelper(context); + } + + public Set<Account> accounts() { + return helper.findAllAccounts(); + } + + public void add(Account account) { + helper.addAccount(account); + } + + public void remove(String id) { + remove(UUID.fromString(id)); + } + + public void remove(UUID id) { + helper.removeAccount(id); + } + + public void remove(Account account) { + remove(account.id); + } + + public Account account(String id) { + return helper.account(id); + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManagerHelper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManagerHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..6ffc8f7b52ebf5f4850964e03ebd0c6cebfc0907 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManagerHelper.java @@ -0,0 +1,203 @@ +/* + * QuasselDroid - Quassel client for Android + * Copyright (C) 2016 Janne Koschinski + * Copyright (C) 2016 Ken Børge Viktil + * Copyright (C) 2016 Magnus Fjell + * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid_ng.util.accounts; + +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteStatement; +import android.support.annotation.NonNull; +import android.util.Log; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class AccountManagerHelper extends SQLiteOpenHelper { + private static final int DATABASE_VERSION = 1; + @NonNull + private static final String DATABASE_NAME = "accounts"; + @NonNull + private static final String TABLE_ACCOUNTS = "accounts"; + + @NonNull + private static final String KEY_ID = "account_id"; + @NonNull + private static final String KEY_NAME = "account_name"; + @NonNull + private static final String KEY_HOST = "account_host"; + @NonNull + private static final String KEY_PORT = "account_port"; + @NonNull + private static final String KEY_USER = "account_user"; + @NonNull + private static final String KEY_PASS = "account_pass"; + + // Again we can only use String.format, as SQL doesn’t support table or column names to be bound + // in prepared statements + @NonNull + private static final String STATEMENT_INSERT = + String.format("INSERT OR IGNORE INTO %s(%s, %s, %s, %s, %s, %s) VALUES (?, ?, ?, ?, ?, ?)", + TABLE_ACCOUNTS, KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS); + @NonNull + private static final String STATEMENT_DELETE = + String.format("DELETE FROM %s WHERE %s = ?", + TABLE_ACCOUNTS, KEY_ID); + + @NonNull + private static final String SPECIFIER_FIND = + String.format("%s = ?", KEY_ID); + + public AccountManagerHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + // Why do we use String.format and not prepared statements? Because we can’t bind table or + // column names in prepared statements + String statement = String.format("CREATE TABLE %s (%s, %s, %s, %s, %s, %s, PRIMARY KEY (%s), UNIQUE(%s));", + TABLE_ACCOUNTS, + KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS, + KEY_ID, + KEY_ID); + db.execSQL(statement); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } + + public boolean addAccount(Account account) { + SQLiteDatabase db = this.getWritableDatabase(); + SQLiteStatement statement = db.compileStatement(STATEMENT_INSERT); + statement.bindString(1, account.id.toString()); + statement.bindString(2, account.name); + statement.bindString(3, account.host); + statement.bindLong(4, account.port); + statement.bindString(5, account.user); + statement.bindString(6, account.pass); + // executeInsert returns -1 if unsuccessful + return statement.executeInsert() != -1; + } + + public boolean removeAccount(UUID id) { + return removeAccount(id.toString()); + } + + public boolean removeAccount(String id) { + SQLiteDatabase db = this.getWritableDatabase(); + SQLiteStatement statement = db.compileStatement(STATEMENT_DELETE); + statement.bindString(1, id); + // executeUpdateDelete returns amount of modified rows + return statement.executeUpdateDelete() > 0; + } + + private Cursor cursorFindAllAccounts() { + SQLiteDatabase db = this.getReadableDatabase(); + return db.query( + // table name + TABLE_ACCOUNTS, + // column names + new String[]{KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS}, + null, + null, + null, + null, + null, + null + ); + } + + private Cursor cursorFindAccount(String id) { + SQLiteDatabase db = this.getReadableDatabase(); + return db.query( + // table name + TABLE_ACCOUNTS, + // column names + new String[]{KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS}, + // where clause + SPECIFIER_FIND, + // binds for where clause + new String[]{id}, + null, + null, + null, + null + ); + } + + @NonNull + public Set<Account> findAllAccounts() { + Cursor cursor = cursorFindAllAccounts(); + + Set<Account> accounts = new HashSet<>(cursor.getCount()); + + if (cursor.moveToFirst()) { + do { + String id = cursor.getString(0); + String name = cursor.getString(1); + String host = cursor.getString(2); + int port = (int) cursor.getLong(3); + String user = cursor.getString(4); + String pass = cursor.getString(5); + try { + accounts.add(new Account(UUID.fromString(id), name, host, port, user, pass)); + } catch (Exception e) { + e.printStackTrace(); + Log.e("AccountManager", "Removing account because invalid", e); + removeAccount(id); + } + } while (cursor.moveToNext()); + } + + return accounts; + } + + public Account account(String query_id) { + Cursor cursor = cursorFindAccount(query_id); + + if (cursor.moveToFirst()) { + do { + String id = cursor.getString(0); + String name = cursor.getString(1); + String host = cursor.getString(2); + int port = (int) cursor.getLong(3); + String user = cursor.getString(4); + String pass = cursor.getString(5); + try { + return new Account(UUID.fromString(id), name, host, port, user, pass); + } catch (Exception e) { + e.printStackTrace(); + Log.e("AccountManager", "Removing account because invalid", e); + removeAccount(id); + } + } while (cursor.moveToNext()); + } + + return null; + } +} diff --git a/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java b/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java index ad9999231d6afcf1155c21800dd1ff5ef344766c..b538a376f0002c500edec378c800d313489ae38f 100644 --- a/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java +++ b/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java @@ -22,6 +22,7 @@ package de.kuschku.util.irc; +import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml new file mode 100644 index 0000000000000000000000000000000000000000..b5751ba8a0b579af4980c9bbbbe591d8ec0171ed --- /dev/null +++ b/app/src/main/res/anim/slide_in_right.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="50%p" android:toXDelta="0" + android:duration="@android:integer/config_mediumAnimTime"/> + <alpha android:fromAlpha="0.0" android:toAlpha="1.0" + android:duration="@android:integer/config_mediumAnimTime" /> +</set> diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml new file mode 100644 index 0000000000000000000000000000000000000000..3d7278e5f54763231d2731de3157da47c1297578 --- /dev/null +++ b/app/src/main/res/anim/slide_out_left.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="0" android:toXDelta="-50%p" + android:duration="@android:integer/config_mediumAnimTime"/> + <alpha android:fromAlpha="1.0" android:toAlpha="0.0" + android:duration="@android:integer/config_mediumAnimTime" /> +</set> + diff --git a/app/src/main/res/color/selectable_button_background.xml b/app/src/main/res/color/selectable_button_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..b14317e104f7cfcd02ed449ca06fc57a4aa1b8fa --- /dev/null +++ b/app/src/main/res/color/selectable_button_background.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:color="#8A777777" /> + <item android:state_focused="true" android:state_enabled="false" android:color="#8A777777" /> + <item android:state_focused="true" android:state_pressed="true" android:color="#8A333333" /> + <item android:state_focused="false" android:state_pressed="true" android:color="#83333333" /> + <item android:state_focused="true" android:color="#8A333333" /> + <item android:color="#8A000000" /> +</selector> diff --git a/app/src/main/res/drawable-hdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-hdpi/ic_arrow_right_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d7b5de459915e9495a781693cf1e88d653644f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_arrow_right_dark.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-hdpi/ic_arrow_right_light.png new file mode 100644 index 0000000000000000000000000000000000000000..65248d20b30ebc08bdaae70baf78c9d02fc8a43f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_arrow_right_light.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_check_dark.png b/app/src/main/res/drawable-hdpi/ic_check_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6adfa198b63624fae6de340de17ea5e8b8a4a61e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_check_dark.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_check_light.png b/app/src/main/res/drawable-hdpi/ic_check_light.png new file mode 100644 index 0000000000000000000000000000000000000000..9e4a0b2b345fd838bf05b06ab39910b58a2131a0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_check_light.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_filter_dark.png b/app/src/main/res/drawable-hdpi/ic_filter_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..cd32743d1373bceb23abe67682c6e32e90f85050 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_filter_dark.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_filter_light.png b/app/src/main/res/drawable-hdpi/ic_filter_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f0d8398f255f0ed47c5870e6c5d7862d43dbc4c9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_filter_light.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_plus_light.png b/app/src/main/res/drawable-hdpi/ic_plus_light.png new file mode 100644 index 0000000000000000000000000000000000000000..5a4cd64e14ea8766c8177043517452442fd96fab Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_plus_light.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-mdpi/ic_arrow_right_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5e98cc7508e3ab33d0c8e80ee40509eaf9ad33d7 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_arrow_right_dark.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-mdpi/ic_arrow_right_light.png new file mode 100644 index 0000000000000000000000000000000000000000..dd79fff4ab4f7f2f9cdc07ef80cd01255b0531f5 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_arrow_right_light.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_check_dark.png b/app/src/main/res/drawable-mdpi/ic_check_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7298777f18e359b6ada165c7d3ced70e22b4b695 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_check_dark.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_check_light.png b/app/src/main/res/drawable-mdpi/ic_check_light.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea8af1fe97bea31625ec101aba650bac33d1d21 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_check_light.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_filter_dark.png b/app/src/main/res/drawable-mdpi/ic_filter_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..ca32e41de952b2a2131e2fdac992b4598cd58e25 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_filter_dark.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_filter_light.png b/app/src/main/res/drawable-mdpi/ic_filter_light.png new file mode 100644 index 0000000000000000000000000000000000000000..41160593a9b8752613e16fe4e073052eadc33f65 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_filter_light.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_plus_light.png b/app/src/main/res/drawable-mdpi/ic_plus_light.png new file mode 100644 index 0000000000000000000000000000000000000000..bc3fd7e379c9db3583f17af658cb0413fe6bccab Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_plus_light.png differ diff --git a/app/src/main/res/drawable-nodpi/bg.png b/app/src/main/res/drawable-nodpi/bg1.png similarity index 100% rename from app/src/main/res/drawable-nodpi/bg.png rename to app/src/main/res/drawable-nodpi/bg1.png diff --git a/app/src/main/res/drawable-nodpi/bg2.jpg~ b/app/src/main/res/drawable-nodpi/bg2.jpg~ new file mode 100644 index 0000000000000000000000000000000000000000..d55595ae5a8581e48647b76cd641524359cd2684 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/bg2.jpg~ differ diff --git a/app/src/main/res/drawable-xhdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-xhdpi/ic_arrow_right_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0463e5cecfcc9b2561a359f689808c3aa6f65e4c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_arrow_right_dark.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-xhdpi/ic_arrow_right_light.png new file mode 100644 index 0000000000000000000000000000000000000000..d2fd86fad0fd9c32a64cb24a45e164567f9e858a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_arrow_right_light.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_check_dark.png b/app/src/main/res/drawable-xhdpi/ic_check_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4eb240b352597fe8b8363b7adf64e8029bb2d01e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_check_dark.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_check_light.png b/app/src/main/res/drawable-xhdpi/ic_check_light.png new file mode 100644 index 0000000000000000000000000000000000000000..3f9b108fc05fe842db406ee6f716e25895a8edcc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_check_light.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_filter_dark.png b/app/src/main/res/drawable-xhdpi/ic_filter_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0bf7bd655ac6930741df031f3d6e576cf4890025 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_filter_dark.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_filter_light.png b/app/src/main/res/drawable-xhdpi/ic_filter_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ac8e1dada9f09656facb872716029a865b0db0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_filter_light.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_plus_light.png b/app/src/main/res/drawable-xhdpi/ic_plus_light.png new file mode 100644 index 0000000000000000000000000000000000000000..949186c670f5bcd3c5c6c3c31c0b91b9352e296c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_plus_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..770d53315bec425a36eb7d0e775d81bed1be6904 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_dark.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_light.png new file mode 100644 index 0000000000000000000000000000000000000000..7f3a9f19a5e6b14e1199d80879bd538e86eee454 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_check_dark.png b/app/src/main/res/drawable-xxhdpi/ic_check_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..c6503fd09eaf4ad9becd2c1a77f5bfdbd1d0b7be Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_check_dark.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_check_light.png b/app/src/main/res/drawable-xxhdpi/ic_check_light.png new file mode 100644 index 0000000000000000000000000000000000000000..392a259e9b36d8967c100c3e9084cb4ca8d83970 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_check_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_filter_dark.png b/app/src/main/res/drawable-xxhdpi/ic_filter_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..ade17c6a028e9d35cca3ab3a0e7054a582f21fc7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_filter_dark.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_filter_light.png b/app/src/main/res/drawable-xxhdpi/ic_filter_light.png new file mode 100644 index 0000000000000000000000000000000000000000..06a23dce33ad8de6f6d4d42df9ac1199b8199684 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_filter_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_plus_light.png b/app/src/main/res/drawable-xxhdpi/ic_plus_light.png new file mode 100644 index 0000000000000000000000000000000000000000..4adbd6d374cb9efb879c5e3cbe557bb8e704749e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_plus_light.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b73aa6909edd82c9ff5cbf21addbd2f2f244bb Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_dark.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_light.png new file mode 100644 index 0000000000000000000000000000000000000000..fd116d1c8f87db1bcae194ca144edbc77d351dc4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_light.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_check_dark.png b/app/src/main/res/drawable-xxxhdpi/ic_check_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..c297f32dd45f46a030b0acd9548eb7382508f385 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_check_dark.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_check_light.png b/app/src/main/res/drawable-xxxhdpi/ic_check_light.png new file mode 100644 index 0000000000000000000000000000000000000000..3400099ded2933bd1a070705ab4981c39aebea06 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_check_light.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_filter_dark.png b/app/src/main/res/drawable-xxxhdpi/ic_filter_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..c54b2eda6c8ecb52b215dabc28d5dddfae6bdba3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_filter_dark.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_filter_light.png b/app/src/main/res/drawable-xxxhdpi/ic_filter_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f70a17b53ee2637a1db7200071d7a143b27f34cb Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_filter_light.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_plus_light.png b/app/src/main/res/drawable-xxxhdpi/ic_plus_light.png new file mode 100644 index 0000000000000000000000000000000000000000..a5464a4b491d6522d5911f2ed293278ebb04792d Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_plus_light.png differ diff --git a/app/src/main/res/layout-sw600dp-land/activity_setup.xml b/app/src/main/res/layout-sw600dp-land/activity_setup.xml new file mode 100644 index 0000000000000000000000000000000000000000..76a3e2ed02d104400f56ba090300250a09c557b2 --- /dev/null +++ b/app/src/main/res/layout-sw600dp-land/activity_setup.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorPrimary"> + + <android.support.v4.view.ViewPager + android:id="@+id/view_pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/ic_arrow_right_dark" + android:layout_gravity="end|bottom" + android:layout_marginRight="80dp" + android:layout_marginEnd="80dp" + android:layout_marginBottom="16dp" + app:elevation="0dip" + app:backgroundTint="#8A000000" + app:fabSize="normal"/> + +</FrameLayout> diff --git a/app/src/main/res/layout-sw600dp-land/slide.xml b/app/src/main/res/layout-sw600dp-land/slide.xml new file mode 100644 index 0000000000000000000000000000000000000000..27cd43569626ff7cb33a4c7f0685c8b6685a3277 --- /dev/null +++ b/app/src/main/res/layout-sw600dp-land/slide.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingLeft="64dp" + android:paddingRight="64dp"> + + <TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/slideAccountcoreTitle" + android:textColor="@android:color/white" + android:textSize="28sp" + android:textStyle="bold" + android:layout_above="@+id/view" + android:layout_toLeftOf="@+id/scrollView2" + android:layout_toStartOf="@+id/scrollView2" + android:gravity="end" + android:paddingRight="64dp" + android:paddingEnd="64dp" /> + + <android.support.v4.widget.Space + android:layout_width="match_parent" + android:layout_height="32dp" + android:layout_centerVertical="true" + android:layout_toLeftOf="@+id/scrollView2" + android:layout_toStartOf="@+id/scrollView2" + android:id="@+id/view" /> + + <TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/slideAccountcoreDescription" + android:textColor="@android:color/white" + android:textSize="16sp" + android:layout_below="@+id/view" + android:layout_toLeftOf="@+id/scrollView2" + android:layout_toStartOf="@+id/scrollView2" + android:gravity="end" + android:paddingRight="64dp" + android:paddingEnd="64dp" /> + + <ScrollView + android:id="@+id/scrollView2" + android:layout_width="400dp" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true"> + + <android.support.v7.widget.CardView + android:id="@+id/content_host" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="400dp" + android:background="@color/md_light_background" /> + + </ScrollView> + +</RelativeLayout> diff --git a/app/src/main/res/layout-sw600dp/activity_setup.xml b/app/src/main/res/layout-sw600dp/activity_setup.xml new file mode 100644 index 0000000000000000000000000000000000000000..e00fb748f1c1e1cf5677c3d4e06321338fecf655 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/activity_setup.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorPrimary"> + + <android.support.v4.view.ViewPager + android:id="@+id/view_pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <FrameLayout + android:layout_width="400dp" + android:layout_height="wrap_content" + android:layout_gravity="bottom|center"> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/ic_arrow_right_dark" + android:layout_gravity="end|bottom" + android:layout_marginRight="16dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="16dp" + app:elevation="0dip" + app:backgroundTint="#8A000000" + app:fabSize="normal" /> + + </FrameLayout> + +</FrameLayout> diff --git a/app/src/main/res/layout-sw600dp/slide.xml b/app/src/main/res/layout-sw600dp/slide.xml new file mode 100644 index 0000000000000000000000000000000000000000..e23f40b3856675418134039a281ca55eb20774b4 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/slide.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="match_parent" + android:layout_width="match_parent"> + + <ScrollView + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_gravity="bottom"> + + <LinearLayout + android:orientation="vertical" + android:layout_width="400dp" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="64dp" + android:padding="32dp" + android:orientation="vertical"> + + <TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textStyle="bold" + android:textColor="@android:color/white" + android:textSize="28sp" + android:layout_marginBottom="32dp" + android:text="@string/slideAccountcoreTitle" + android:id="@+id/title" /> + + <TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/white" + android:textSize="16sp" + android:text="@string/slideAccountcoreDescription" + android:id="@+id/description" /> + + </LinearLayout> + + <android.support.v7.widget.CardView + android:id="@+id/content_host" + android:minHeight="400dp" + android:background="@color/md_light_background" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + </LinearLayout> + + </ScrollView> + +</FrameLayout> diff --git a/app/src/main/res/layout-w720dp/activity_main.xml b/app/src/main/res/layout-w720dp/activity_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..2193aacb69d546053146a73c289d7c335ab63c9f --- /dev/null +++ b/app/src/main/res/layout-w720dp/activity_main.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ui.chat.MainActivity"> + + <FrameLayout + android:id="@+id/drawer_host" + android:layout_width="300dp" + android:layout_height="match_parent" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <include layout="@layout/widget_actionbar" /> + + <FrameLayout + android:id="@+id/content_host" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/activity_accountchooser.xml b/app/src/main/res/layout/activity_accountchooser.xml new file mode 100644 index 0000000000000000000000000000000000000000..d47d053c3359e3723e986f664708f791fec2679d --- /dev/null +++ b/app/src/main/res/layout/activity_accountchooser.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="match_parent" + android:layout_height="match_parent"> + +</LinearLayout> diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml index 3ccfa08ec1ab58135896bede244578fa213f4adc..50b28109bf9a1412377fd487091ac6b5d1a251b0 100644 --- a/app/src/main/res/layout/activity_chat.xml +++ b/app/src/main/res/layout/activity_chat.xml @@ -26,7 +26,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - <include layout="@layout/toolbar" /> + <include layout="@layout/widget_actionbar" /> <com.sothree.slidinguppanel.SlidingUpPanelLayout android:id="@+id/sliding_layout" @@ -38,9 +38,9 @@ app:umanoScrollableView="@+id/chatline_scroller" app:umanoShadowHeight="4dp"> - <include layout="@layout/content_main" /> + <include layout="@layout/fragment_chat" /> - <include layout="@layout/slider_main" /> + <include layout="@layout/widget_slider" /> </com.sothree.slidinguppanel.SlidingUpPanelLayout> diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/activity_main.xml similarity index 72% rename from app/src/main/res/layout/content_main.xml rename to app/src/main/res/layout/activity_main.xml index e5ab0fb3d7e971b0c693e98726229c2d4cc93246..50c6366d12737caaaec9bd999ccbf2bd37b177c8 100644 --- a/app/src/main/res/layout/content_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -20,17 +20,19 @@ ~ with this program. If not, see <http://www.gnu.org/licenses/>. --> -<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/swipe_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="?attr/colorBackground" - tools:showIn="@layout/activity_chat"> + android:orientation="vertical" + tools:context=".ui.chat.MainActivity"> - <android.support.v7.widget.RecyclerView - android:id="@+id/messages" + <include layout="@layout/widget_actionbar" /> + + <FrameLayout + android:id="@+id/content_host" android:layout_width="match_parent" - android:layout_height="match_parent" - android:clickable="true" /> -</android.support.v4.widget.SwipeRefreshLayout> + android:layout_height="match_parent" /> + +</LinearLayout> diff --git a/app/src/main/res/layout/activity_setup.xml b/app/src/main/res/layout/activity_setup.xml new file mode 100644 index 0000000000000000000000000000000000000000..c8168d03a062b5041646cde1e3caff7d2342f3e6 --- /dev/null +++ b/app/src/main/res/layout/activity_setup.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorPrimary"> + + <android.support.v4.view.ViewPager + android:id="@+id/view_pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/ic_arrow_right_dark" + android:layout_gravity="end|bottom" + android:layout_marginRight="16dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="16dp" + app:elevation="0dip" + app:backgroundTint="#8A000000" + app:fabSize="normal" /> + +</FrameLayout> diff --git a/app/src/main/res/layout/fragment_chat.xml b/app/src/main/res/layout/fragment_chat.xml new file mode 100644 index 0000000000000000000000000000000000000000..a38ddea7544ad89dcd418f1e61f8afa0c8a94433 --- /dev/null +++ b/app/src/main/res/layout/fragment_chat.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<com.sothree.slidinguppanel.SlidingUpPanelLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/sliding_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="bottom" + android:orientation="vertical" + app:umanoPanelHeight="?attr/actionBarSize" + app:umanoScrollableView="@+id/chatline_scroller" + app:umanoShadowHeight="4dp" + android:background="?attr/colorBackground" + tools:showIn="@layout/activity_chat"> + + <android.support.v4.widget.SwipeRefreshLayout + android:id="@+id/swipe_view" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <android.support.v7.widget.RecyclerView + android:id="@+id/messages" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clickable="true" /> + </android.support.v4.widget.SwipeRefreshLayout> + + <include layout="@layout/widget_slider" /> + +</com.sothree.slidinguppanel.SlidingUpPanelLayout> diff --git a/app/src/main/res/layout/fragment_loading.xml b/app/src/main/res/layout/fragment_loading.xml new file mode 100644 index 0000000000000000000000000000000000000000..997f5c18faa1dd1cd87c21cff128ff46570659c6 --- /dev/null +++ b/app/src/main/res/layout/fragment_loading.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorBackground"> + + <LinearLayout + android:orientation="vertical" + android:layout_width="240dp" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_centerHorizontal="true"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <TextView + android:layout_width="0dip" + android:layout_weight="1" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.AppCompat.Caption" + android:text="Connecting" + android:id="@+id/label" /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.AppCompat.Caption" + android:text="1/15" + android:id="@+id/count" /> + </LinearLayout> + <ProgressBar + style="@style/Widget.AppCompat.ProgressBar.Horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:indeterminate="true" + android:id="@+id/progressBar" /> + </LinearLayout> +</RelativeLayout> diff --git a/app/src/main/res/layout/slide.xml b/app/src/main/res/layout/slide.xml new file mode 100644 index 0000000000000000000000000000000000000000..884a2531142bfe69d3b964c1478f7a1ba57c5401 --- /dev/null +++ b/app/src/main/res/layout/slide.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="match_parent" + android:layout_width="match_parent"> + + <ScrollView + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_gravity="bottom"> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity=""> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="96dp" + android:padding="32dp" + android:orientation="vertical"> + + <TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textStyle="bold" + android:textColor="@android:color/white" + android:textSize="28sp" + android:layout_marginBottom="32dp" + android:text="@string/slideAccountcoreTitle" + android:id="@+id/title" /> + + <TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/white" + android:textSize="16sp" + android:text="@string/slideAccountcoreDescription" + android:id="@+id/description" /> + + </LinearLayout> + + <android.support.v7.widget.CardView + android:id="@+id/content_host" + android:minHeight="240dp" + android:background="@color/md_light_background" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + </LinearLayout> + + </ScrollView> + +</FrameLayout> diff --git a/app/src/main/res/layout/slide_account_core.xml b/app/src/main/res/layout/slide_account_core.xml new file mode 100644 index 0000000000000000000000000000000000000000..de5791d490fa396ceb37395672f46843bae32386 --- /dev/null +++ b/app/src/main/res/layout/slide_account_core.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="32dp"> + + <android.support.design.widget.TextInputLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="Hostname"> + <android.support.v7.widget.AppCompatEditText + android:id="@+id/host" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textUri" /> + </android.support.design.widget.TextInputLayout> + + <android.support.design.widget.TextInputLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="Port"> + <android.support.v7.widget.AppCompatEditText + android:id="@+id/port" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="number" /> + </android.support.design.widget.TextInputLayout> + +</LinearLayout> diff --git a/app/src/main/res/layout/slide_account_name.xml b/app/src/main/res/layout/slide_account_name.xml new file mode 100644 index 0000000000000000000000000000000000000000..49c8e4a5a240026ab637badd2cbab6be293413a9 --- /dev/null +++ b/app/src/main/res/layout/slide_account_name.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="32dp"> + + <android.support.design.widget.TextInputLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="Account Name"> + <android.support.v7.widget.AppCompatEditText + android:id="@+id/name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textEmailSubject" /> + </android.support.design.widget.TextInputLayout> + +</LinearLayout> diff --git a/app/src/main/res/layout/slide_account_user.xml b/app/src/main/res/layout/slide_account_user.xml new file mode 100644 index 0000000000000000000000000000000000000000..88a9fcba80ed8ab193858c05626a089b8542ec54 --- /dev/null +++ b/app/src/main/res/layout/slide_account_user.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="32dp"> + + <android.support.design.widget.TextInputLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="Username"> + <android.support.v7.widget.AppCompatEditText + android:id="@+id/user" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textVisiblePassword" /> + </android.support.design.widget.TextInputLayout> + + <android.support.design.widget.TextInputLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="Password"> + <android.support.v7.widget.AppCompatEditText + android:id="@+id/pass" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" /> + </android.support.design.widget.TextInputLayout> + +</LinearLayout> diff --git a/app/src/main/res/layout/slide_select.xml b/app/src/main/res/layout/slide_select.xml new file mode 100644 index 0000000000000000000000000000000000000000..9cd2f7aa6b8cde3d0acf9f822a39def3a54d3256 --- /dev/null +++ b/app/src/main/res/layout/slide_select.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<android.support.v7.widget.RecyclerView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="400dp" /> diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/widget_actionbar.xml similarity index 100% rename from app/src/main/res/layout/toolbar.xml rename to app/src/main/res/layout/widget_actionbar.xml diff --git a/app/src/main/res/layout/widget_core_account.xml b/app/src/main/res/layout/widget_core_account.xml new file mode 100644 index 0000000000000000000000000000000000000000..1705a7400a23a8f5db92423eb244c713b2e146d5 --- /dev/null +++ b/app/src/main/res/layout/widget_core_account.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="@dimen/material_drawer_item_profile" + android:orientation="horizontal" + android:paddingEnd="@dimen/material_drawer_vertical_padding" + android:paddingLeft="@dimen/material_drawer_vertical_padding" + android:paddingRight="@dimen/material_drawer_vertical_padding" + android:paddingStart="@dimen/material_drawer_vertical_padding"> + + <LinearLayout + android:layout_width="@dimen/material_drawer_item_profile_icon_width" + android:layout_height="@dimen/material_drawer_item_profile" + android:paddingBottom="@dimen/material_drawer_item_profile_icon_padding" + android:paddingEnd="@dimen/material_drawer_item_profile_icon_padding_right" + android:paddingLeft="0dp" + android:paddingRight="@dimen/material_drawer_item_profile_icon_padding_right" + android:paddingStart="0dp" + android:paddingTop="@dimen/material_drawer_item_profile_icon_padding"> + + <android.support.v7.widget.AppCompatRadioButton + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:id="@+id/account_select" /> + + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_vertical|start" + android:orientation="vertical" + android:paddingEnd="0dp" + android:paddingLeft="@dimen/material_drawer_padding" + android:paddingRight="0dp" + android:paddingStart="@dimen/material_drawer_padding"> + + <TextView + android:id="@+id/account_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif-medium" + android:gravity="center_vertical|start" + android:lines="1" + android:paddingRight="@dimen/material_drawer_item_primary_icon_padding_right" + android:singleLine="true" + android:textDirection="anyRtl" + android:textSize="@dimen/material_drawer_item_profile_text" + tools:text="Remote" /> + + <TextView + android:id="@+id/account_description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif" + android:gravity="center_vertical|start" + android:lines="1" + android:singleLine="true" + android:textDirection="anyRtl" + android:textSize="@dimen/material_drawer_item_profile_description" + tools:text="kuschku on kuschku.de" /> + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/widget_core_account_add.xml b/app/src/main/res/layout/widget_core_account_add.xml new file mode 100644 index 0000000000000000000000000000000000000000..52382d73349b892fcd6cab188b0cd6451caedf26 --- /dev/null +++ b/app/src/main/res/layout/widget_core_account_add.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="@dimen/material_drawer_item_profile" + android:orientation="horizontal" + android:paddingEnd="@dimen/material_drawer_vertical_padding" + android:paddingLeft="@dimen/material_drawer_vertical_padding" + android:paddingRight="@dimen/material_drawer_vertical_padding" + android:paddingStart="@dimen/material_drawer_vertical_padding"> + + <LinearLayout + android:layout_width="@dimen/material_drawer_item_profile_icon_width" + android:layout_height="@dimen/material_drawer_item_profile" + android:paddingBottom="@dimen/material_drawer_item_profile_icon_padding" + android:paddingEnd="@dimen/material_drawer_item_profile_icon_padding_right" + android:paddingLeft="0dp" + android:paddingRight="@dimen/material_drawer_item_profile_icon_padding_right" + android:paddingStart="0dp" + android:paddingTop="@dimen/material_drawer_item_profile_icon_padding"> + + <ImageView + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="center_vertical" + android:src="@drawable/ic_plus_light" /> + + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_vertical|start" + android:orientation="vertical" + android:paddingEnd="0dp" + android:paddingLeft="@dimen/material_drawer_padding" + android:paddingRight="0dp" + android:paddingStart="@dimen/material_drawer_padding"> + + <TextView + android:id="@+id/account_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif-medium" + android:gravity="center_vertical|start" + android:lines="1" + android:paddingRight="@dimen/material_drawer_item_primary_icon_padding_right" + android:singleLine="true" + android:textDirection="anyRtl" + android:textSize="@dimen/material_drawer_item_profile_text" + android:text="Add Account" /> + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/widget_editor.xml b/app/src/main/res/layout/widget_editor.xml index 5031c7cbcd80de29fc0be0da5f202264424640ac..a41550b8df07ebd2f05270b02ac5cbe5fd47d6b6 100644 --- a/app/src/main/res/layout/widget_editor.xml +++ b/app/src/main/res/layout/widget_editor.xml @@ -24,8 +24,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingBottom="@dimen/message_history_panel_height" - tools:showIn="@layout/slider_main"> + tools:showIn="@layout/widget_slider"> <ScrollView android:id="@+id/chatline_scroller" diff --git a/app/src/main/res/layout/slider_main.xml b/app/src/main/res/layout/widget_slider.xml similarity index 97% rename from app/src/main/res/layout/slider_main.xml rename to app/src/main/res/layout/widget_slider.xml index a83f5d5b0fcfd18dd87f70ad9ec9e20f1ee757cf..e26f756b9359256fde15bc9d9aeb01e88c3e8f0c 100644 --- a/app/src/main/res/layout/slider_main.xml +++ b/app/src/main/res/layout/widget_slider.xml @@ -32,7 +32,7 @@ android:gravity="bottom" sothree:umanoFadeColor="?attr/colorBackgroundCard" sothree:umanoOverlay="true" - sothree:umanoPanelHeight="@dimen/message_history_panel_height" + sothree:umanoPanelHeight="0dip" sothree:umanoScrollableView="@+id/msg_history" sothree:umanoShadowHeight="0.0dip" tools:showIn="@layout/activity_chat"> diff --git a/app/src/main/res/menu/chat.xml b/app/src/main/res/menu/chat.xml index e5cbf8eae2cf96727e43514a581e8b51551215fa..5b232764cb900c0d3df9db7793606baabdd2a9ae 100644 --- a/app/src/main/res/menu/chat.xml +++ b/app/src/main/res/menu/chat.xml @@ -22,10 +22,14 @@ <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/action_reauth" + android:title="Reauth" + app:showAsAction="ifRoom" /> <item android:id="@+id/action_hide_events" - android:icon="@android:drawable/ic_menu_sort_by_size" + android:icon="@drawable/ic_filter_dark" android:orderInCategory="100" android:title="@string/labelHideEvents" - app:showAsAction="never" /> + app:showAsAction="ifRoom" /> </menu> diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..24ea19facc5101226f994ef3483b970269489c88 --- /dev/null +++ b/app/src/main/res/values-v21/styles.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<resources> + <style name="Base.SetupTheme" parent="Theme.AppCompat.Light.NoActionBar"> + <item name="android:windowTranslucentStatus">true</item> + </style> +</resources> diff --git a/app/src/main/res/values-w720dp/bools.xml b/app/src/main/res/values-w720dp/bools.xml new file mode 100644 index 0000000000000000000000000000000000000000..533e6f4eadfe231d29736242ea846d8b4253d44f --- /dev/null +++ b/app/src/main/res/values-w720dp/bools.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<resources> + <bool name="isTablet">true</bool> +</resources> diff --git a/app/src/main/res/values-w720dp/styles.xml b/app/src/main/res/values-w720dp/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..e822c3c732598c21402f9760623dab66f8412c48 --- /dev/null +++ b/app/src/main/res/values-w720dp/styles.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<resources> + <style name="BaseTheme" parent="MaterialDrawerTheme" /> + <style name="BaseTheme.Light" parent="MaterialDrawerTheme.Light.DarkToolbar" /> +</resources> diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 986086c9dc4ce663a209e80369346c9584e057cb..5ab6942105e71f24bf78450946ae0c69553fcab0 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -21,8 +21,6 @@ --> <resources> - <attr name="colorAccentFocus" /> - <!-- sender colors --> <attr name="senderColor0" format="color" /> @@ -88,6 +86,7 @@ <attr name="iconFormatFill" format="reference" /> <attr name="iconHistory" format="reference" /> <attr name="iconDebug" format="reference" /> + <attr name="iconFilter" format="reference" /> <attr name="cardStyle" format="reference" /> </resources> diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml new file mode 100644 index 0000000000000000000000000000000000000000..26d3877c3d5a22a85ccc4670105434059aa24fce --- /dev/null +++ b/app/src/main/res/values/bools.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<resources> + <bool name="isTablet">false</bool> +</resources> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b0c2c55c9d87f134369b4efbe58fe847893cc44a..6594d1de52c7ba13099f531ac239953f5914155d 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -27,5 +27,5 @@ <dimen name="message_horizontal">8dp</dimen> <dimen name="message_vertical">4dp</dimen> - <dimen name="message_history_panel_height">0dip</dimen> + <dimen name="circular_button_size">56dp</dimen> </resources> diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index 49842553e87f668fdcf83134b704bee7fd60fc37..f5667ed02f62737dad37805116bf5cb501cd4094 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -23,4 +23,6 @@ <resources> <item name="custom_url_span" type="id" /> <item name="custom_channel_span" type="id" /> + <item name="item_create_account" type="id" /> + <item name="item_account" type="id" /> </resources> diff --git a/app/src/main/res/values/preferences.xml b/app/src/main/res/values/preferences.xml new file mode 100644 index 0000000000000000000000000000000000000000..d451c47cbed7a904c6d1e321092151f9f4ae2adb --- /dev/null +++ b/app/src/main/res/values/preferences.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<resources> + <string name="preference_theme" translatable="false">selectedtheme</string> + <string name="preference_theme_title">Theme</string> + <string-array name="preference_theme_entries"> + <item>Google® Material (Light)</item> + <item>Google® Material (Dark)</item> + <item>Quassel™ (Light)</item> + <item>Quassel™ (Dark)</item> + <!--<item>Solarized (Light)</item>--> + <item>Solarized (Dark)</item> + </string-array> + <string-array name="preference_theme_values"> + <item>MATERIAL_LIGHT</item> + <item>MATERIAL_DARK</item> + <item>QUASSEL_LIGHT</item> + <item>QUASSEL_DARK</item> + <!--<item>SOLARIZED_LIGHT</item>--> + <item>SOLARIZED_DARK</item> + </string-array> +</resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e9564f3292a120b083f76a7e38c8bb1c804fb9e8..80916c85a24ae0a775aea73f03eb037fdb05455d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -28,33 +28,6 @@ <string name="appLinkCommunityTitle">Community</string> <string name="appLinkCommunityUrl" translatable="false">https://plus.google.com/communities/104094956084217666662</string> - <!-- Message format strings --> - <string name="usernameHostmask">%1$s (%2$s)</string> - - <string name="messagePlain">%1$s: %2$s</string> - - <string name="messageJoin">%1$s has joined %2$s</string> - - <string name="messagePart">%1$s has left %2$s</string> - <string name="messagePartExtra">"%1$s has left %2$s (%3$s)</string> - - <string name="messageQuit">%1$s has quit</string> - <string name="messageQuitExtra">%1$s has quit (%2$s)</string> - - <string name="messageKill">%1$s was killed: %2$s</string> - - <string name="messageKick">%1$s has kicked %2$s from %3$s</string> - <string name="messageKickExtra">%1$s has kicked %2$s from %3$s: %4$s</string> - - <string name="messageMode">Mode %1$s by %2$s</string> - - <string name="messageNickSelf">You are now known as %1$s</string> - <string name="messageNickOther">%1$s is now known as %2$s</string> - - <string name="messageDayChange">{ Day changed to %1$s }</string> - - <string name="messageAction">* %1$s %2$s</string> - <!-- Editor UI --> <string name="placeholder">Write a message…</string> <string name="formatBold">Bold</string> @@ -66,7 +39,7 @@ <!-- Actions --> <string name="labelLogin">Login</string> <string name="labelCancel">Cancel</string> - <string name="labelConnect">Connect</string> + <string name="labelReconnect">Connect</string> <string name="labelSettings">Settings</string> <string name="labelStatusBuffer">Status Buffer</string> <string name="labelAddress">Address</string> @@ -78,5 +51,18 @@ <string name="labelHideEvents">Hide events</string> <string name="warningCertificate">Do you trust this certificate?</string> - <string name="labelDebug">Debug</string> + + <string name="labelUserOnHost">%1$s on %2$s</string> + + <string name="slideAccountcoreTitle">The Core</string> + <string name="slideAccountcoreDescription">First, please choose which server your core is hosted on – if you don’t know what a core is, click [here]</string> + + <string name="slideAccountuserTitle">Your Account</string> + <string name="slideAccountuserDescription">Now, please enter the username and password for your account on the core. If you just created that core, we’ll set up this account for you</string> + + <string name="slideAccountselectTitle">Select Account</string> + <string name="slideAccountselectDescription">Please select an account from the list or add one</string> + + <string name="slideAccountnameTitle">Customize Account</string> + <string name="slideAccountnameDescription">Give this account a name and icon</string> </resources> diff --git a/app/src/main/res/values/strings_format.xml b/app/src/main/res/values/strings_format.xml new file mode 100644 index 0000000000000000000000000000000000000000..852d78f036ea0f1a41794883ba2aa124b1d24868 --- /dev/null +++ b/app/src/main/res/values/strings_format.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ QuasselDroid - Quassel client for Android + ~ Copyright (C) 2016 Janne Koschinski + ~ Copyright (C) 2016 Ken Børge Viktil + ~ Copyright (C) 2016 Magnus Fjell + ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org> + ~ + ~ This program is free software: you can redistribute it and/or modify it + ~ under the terms of the GNU General Public License as published by the Free + ~ Software Foundation, either version 3 of the License, or (at your option) + ~ any later version. + ~ + ~ This program is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ~ GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along + ~ with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<resources> + <!-- Message format strings --> + <string name="usernameHostmask">%1$s (%2$s)</string> + + <string name="messagePlain">%1$s: %2$s</string> + + <string name="messageJoin">%1$s has joined %2$s</string> + + <string name="messagePart">%1$s has left %2$s</string> + <string name="messagePartExtra">"%1$s has left %2$s (%3$s)</string> + + <string name="messageQuit">%1$s has quit</string> + <string name="messageQuitExtra">%1$s has quit (%2$s)</string> + + <string name="messageKill">%1$s was killed: %2$s</string> + + <string name="messageKick">%1$s has kicked %2$s from %3$s</string> + <string name="messageKickExtra">%1$s has kicked %2$s from %3$s: %4$s</string> + + <string name="messageMode">Mode %1$s by %2$s</string> + + <string name="messageNickSelf">You are now known as %1$s</string> + <string name="messageNickOther">%1$s is now known as %2$s</string> + + <string name="messageDayChange">{ Day changed to %1$s }</string> + + <string name="messageAction">* %1$s %2$s</string> +</resources> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index d23e2803f43246c7af044316d53251491f86ab45..3ac174f46de126d95fb15e97458d43e4b721085a 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -20,17 +20,22 @@ --> <resources> + <style name="BaseTheme" parent="MaterialDrawerTheme.TranslucentStatus" /> + <style name="BaseTheme.Light" parent="MaterialDrawerTheme.Light.DarkToolbar.TranslucentStatus" /> <!-- Base application theme. --> - <style name="AppTheme" parent="MaterialDrawerTheme.TranslucentStatus"> + <style name="AppTheme" parent="BaseTheme"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> - <item name="colorAccentFocus">@color/colorAccentFocus</item> - <item name="colorControlHighlight">@color/colorAccentFocus</item> <item name="windowActionModeOverlay">true</item> + + <item name="material_drawer_background">?attr/colorBackground</item> + <item name="material_drawer_primary_text">?attr/colorForeground</item> + <item name="material_drawer_primary_icon">?attr/colorForeground</item> + <item name="material_drawer_secondary_text">?attr/colorForegroundSecondary</item> <item name="iconFormatBold">@drawable/ic_format_bold_dark</item> <item name="iconFormatItalic">@drawable/ic_format_italic_dark</item> @@ -39,20 +44,24 @@ <item name="iconFormatFill">@drawable/ic_format_fill_dark</item> <item name="iconHistory">@drawable/ic_history_dark</item> <item name="iconDebug">@drawable/ic_bug_dark</item> + <item name="iconFilter">@drawable/ic_filter_dark</item> <item name="cardStyle">@style/CardView.Dark</item> </style> - <style name="AppTheme.Light" parent="MaterialDrawerTheme.Light.DarkToolbar.TranslucentStatus"> + <style name="AppTheme.Light" parent="BaseTheme.Light"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> - <item name="colorAccentFocus">@color/colorAccentFocus</item> - <item name="colorControlHighlight">@color/colorAccentFocus</item> <item name="windowActionModeOverlay">true</item> + <item name="material_drawer_background">?attr/colorBackground</item> + <item name="material_drawer_primary_text">?attr/colorForeground</item> + <item name="material_drawer_primary_icon">?attr/colorForeground</item> + <item name="material_drawer_secondary_text">?attr/colorForegroundSecondary</item> + <item name="iconFormatBold">@drawable/ic_format_bold_light</item> <item name="iconFormatItalic">@drawable/ic_format_italic_light</item> <item name="iconFormatUnderline">@drawable/ic_format_underline_light</item> @@ -60,10 +69,22 @@ <item name="iconFormatFill">@drawable/ic_format_fill_light</item> <item name="iconHistory">@drawable/ic_history_light</item> <item name="iconDebug">@drawable/ic_bug_light</item> + <item name="iconFilter">@drawable/ic_filter_light</item> <item name="cardStyle">@style/CardView.Light</item> </style> + <style name="Base.SetupTheme" parent="Theme.AppCompat.Light.NoActionBar" /> + + <style name="SetupTheme" parent="Theme.AppCompat.Light.NoActionBar"> + <!-- Customize your theme here. --> + <item name="colorPrimary">@color/colorPrimary</item> + <item name="colorPrimaryDark">@color/colorPrimaryDark</item> + <item name="colorAccent">@color/colorAccent</item> + <item name="colorControlHighlight">@color/colorAccentFocus</item> + <item name="windowActionModeOverlay">true</item> + </style> + <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark" /> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 1805fe606cdf6b2ea4402c55e44667bfd0e0b247..ee979f7c7e542b6278c6fc406987368e0e5db7b2 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -220,4 +220,59 @@ <item name="colorTintMessage">#2277dd</item> <item name="colorTintHighlight">#ff8811</item> </style> + + <style name="Solarized_Dark" parent="AppTheme"> + <item name="colorPrimary">?attr/colorBackgroundCard</item> + <item name="colorPrimaryDark">?attr/colorBackground</item> + <item name="colorAccent">#B58900</item> + <item name="colorControlHighlight">#40B58900</item> + + <item name="senderColor0">#B58900</item> + <item name="senderColor1">#CB4B16</item> + <item name="senderColor2">#DC322f</item> + <item name="senderColor3">#D33682</item> + <item name="senderColor4">#6C71C4</item> + <item name="senderColor5">#268BD2</item> + <item name="senderColor6">#2AA198</item> + <item name="senderColor7">#859900</item> + <item name="senderColor8">#D5A920</item> + <item name="senderColor9">#EB6B36</item> + <item name="senderColorA">#FC524f</item> + <item name="senderColorB">#F356A2</item> + <item name="senderColorC">#8C91E4</item> + <item name="senderColorD">#46ABF2</item> + <item name="senderColorE">#4AC1B8</item> + <item name="senderColorF">#657900</item> + + <item name="mircColor0">#ffffff</item> + <item name="mircColor1">#000000</item> + <item name="mircColor2">#1155aa</item> + <item name="mircColor3">#008000</item> + <item name="mircColor4">#ff0000</item> + <item name="mircColor5">#800000</item> + <item name="mircColor6">#800080</item> + <item name="mircColor7">#ffa500</item> + <item name="mircColor8">#ffff00</item> + <item name="mircColor9">#00ff00</item> + <item name="mircColorA">#008080</item> + <item name="mircColorB">#00ffff</item> + <item name="mircColorC">#1155ff</item> + <item name="mircColorD">#ff00ff</item> + <item name="mircColorE">#808080</item> + <item name="mircColorF">#c0c0c0</item> + + <item name="colorForeground">#839495</item> + <item name="colorForegroundHighlight">#839495</item> + <item name="colorForegroundSecondary">#576A66</item> + <item name="colorForegroundAction">#268BD2</item> + + <item name="colorBackground">#002B36</item> + <item name="colorBackgroundHighlight">#268bd2</item> + <item name="colorBackgroundSecondary">#073642</item> + <item name="colorBackgroundCard">#073642</item> + + <item name="colorTintActivity">#88cc33</item> + <item name="colorTintMessage">#2277dd</item> + <item name="colorTintHighlight">#ff8811</item> + </style> </resources> diff --git a/aspm b/aspm deleted file mode 160000 index 9a6dc7fbbf275b54ab74a66a282769f63e9dc120..0000000000000000000000000000000000000000 --- a/aspm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9a6dc7fbbf275b54ab74a66a282769f63e9dc120 diff --git a/install.sh b/install.sh index 0043c696996d74cf9c4a0f85bf9b1d63f65a6a2e..2f12876bcfdc848ef78ce6358a260c1489b1aeeb 100755 --- a/install.sh +++ b/install.sh @@ -14,15 +14,6 @@ cd .. cp AndroidSlidingUpPanel/library/build/outputs/aar/library-release.aar app/libs/library-release.aar rm AndroidSlidingUpPanel/local.properties -# Build aspm -echo sdk.dir=$ANDROID_HOME > aspm/local.properties -cd aspm -gradle clean build jar shadowJar -cd .. -cp aspm/annotations/build/libs/annotations.jar app/libs/annotations.jar -cp aspm/compiler/build/libs/compiler-all.jar app/libs/compiler-all.jar -rm aspm/local.properties - # Build QuasselDroidNG echo sdk.dir=$ANDROID_HOME > local.properties gradle clean assembleRelease -x lintVitalRelease