introduce settings activity

This commit is contained in:
Daniel Gultsch 2023-02-20 10:09:20 +01:00
parent cdcd323c36
commit fe9b3b8ed9
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
18 changed files with 197 additions and 47 deletions

View file

@ -88,6 +88,9 @@ dependencies {
implementation "androidx.room:room-guava:$rootProject.ext.roomVersion"
annotationProcessor "androidx.room:room-compiler:$rootProject.ext.roomVersion"
implementation "androidx.preference:preference:$rootProject.ext.preferenceVersion"
implementation "androidx.security:security-crypto:1.0.0"

View file

@ -93,12 +93,15 @@
<activity
android:name="im.conversations.android.ui.activity.MainActivity"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="im.conversations.android.ui.activity.SettingsActivity" />
<activity
android:name="im.conversations.android.ui.activity.SetupActivity"
android:windowSoftInputMode="adjustResize" />

View file

@ -2,6 +2,7 @@ package im.conversations.android;
import android.app.Application;
import androidx.appcompat.app.AppCompatDelegate;
import com.google.android.material.color.DynamicColors;
import im.conversations.android.dns.Resolver;
import im.conversations.android.notification.Channels;
import im.conversations.android.xmpp.ConnectionPool;
@ -31,6 +32,6 @@ public class Conversations extends Application {
ConnectionPool.getInstance(this).reconfigure();
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); // For night mode theme
// DynamicColors.applyToActivitiesIfAvailable(this);
DynamicColors.applyToActivitiesIfAvailable(this);
}
}

View file

@ -1,7 +1,6 @@
package im.conversations.android.database.model;
import androidx.annotation.NonNull;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
@ -33,9 +32,6 @@ public class AccountIdentifier implements ChatFilter {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("address", address)
.toString();
return MoreObjects.toStringHelper(this).add("id", id).add("address", address).toString();
}
}

View file

@ -1,22 +1,15 @@
package im.conversations.android.database.model;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import java.util.StringJoiner;
public class GroupIdentifier implements ChatFilter {
public final long id;
public final String name;
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("name", name)
.toString();
return MoreObjects.toStringHelper(this).add("id", id).add("name", name).toString();
}
public GroupIdentifier(long id, String name) {

View file

@ -1,15 +1,11 @@
package im.conversations.android.ui;
import android.content.Intent;
import com.google.common.base.Strings;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.impl.JidCreate;
import im.conversations.android.database.model.AccountIdentifier;
import im.conversations.android.database.model.ChatFilter;
import im.conversations.android.database.model.GroupIdentifier;
import org.jxmpp.jid.impl.JidCreate;
public final class Intents {
@ -47,7 +43,7 @@ public final class Intents {
throw new IllegalArgumentException("Intent doe not specify an action");
}
if (ACTION_FILTER_CHATS_BY_ACCOUNT.equals(action)) {
final var id = intent.getLongExtra(EXTRA_ACCOUNT_ID,-1);
final var id = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
final var address = intent.getStringExtra(EXTRA_ACCOUNT_ADDRESS);
if (id < 0 || Strings.isNullOrEmpty(address)) {
throw new IllegalArgumentException("account filter intent lacks extras");
@ -55,7 +51,7 @@ public final class Intents {
return new AccountIdentifier(id, JidCreate.bareFromOrThrowUnchecked(address));
}
if (ACTION_FILTER_CHATS_BY_GROUP.equals(action)) {
final var id = intent.getLongExtra(EXTRA_GROUP_ID,-1);
final var id = intent.getLongExtra(EXTRA_GROUP_ID, -1);
final var name = intent.getStringExtra(EXTRA_GROUP_NAME);
if (id < 0 || Strings.isNullOrEmpty(name)) {
throw new IllegalArgumentException("group filter intent lack address");

View file

@ -0,0 +1,27 @@
package im.conversations.android.ui.activity;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import im.conversations.android.R;
import im.conversations.android.databinding.ActivitySettingsBinding;
import im.conversations.android.service.ForegroundService;
import im.conversations.android.ui.Activities;
import im.conversations.android.ui.fragment.settings.MainSettingsFragment;
public class SettingsActivity extends AppCompatActivity {
private ActivitySettingsBinding binding;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ForegroundService.start(this);
this.binding = DataBindingUtil.setContentView(this, R.layout.activity_settings);
Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, new MainSettingsFragment())
.commit();
}
}

View file

@ -3,9 +3,11 @@ package im.conversations.android.ui.fragment.main;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
@ -17,6 +19,7 @@ import im.conversations.android.database.model.ChatFilter;
import im.conversations.android.database.model.GroupIdentifier;
import im.conversations.android.databinding.FragmentOverviewBinding;
import im.conversations.android.ui.Intents;
import im.conversations.android.ui.activity.SettingsActivity;
import im.conversations.android.ui.activity.SetupActivity;
import im.conversations.android.ui.model.OverviewViewModel;
import java.util.List;
@ -55,24 +58,7 @@ public class OverviewFragment extends Fragment {
window.setStatusBarColor(SurfaceColors.SURFACE_0.getColor(activity));
}
});
binding.navigationView.setNavigationItemSelectedListener(
item -> {
if (item.getItemId() == R.id.chats) {
setChatFilter(null);
return true;
}
if (item.getItemId() == R.id.add_account) {
startActivity(new Intent(requireContext(), SetupActivity.class));
binding.drawerLayout.close();
return false;
}
final var intent = item.getIntent();
if (intent == null) {
return false;
}
setChatFilter(Intents.toChatFilter(intent));
return true;
});
binding.navigationView.setNavigationItemSelectedListener(this::onNavigationItemSelected);
binding.navigationView.setCheckedItem(R.id.chats);
this.overviewViewModel
.getAccounts()
@ -84,6 +70,31 @@ public class OverviewFragment extends Fragment {
return binding.getRoot();
}
private boolean onNavigationItemSelected(final MenuItem menuItem) {
if (menuItem.getItemId() == R.id.chats) {
setChatFilter(null);
return true;
}
if (menuItem.getItemId() == R.id.add_account) {
return startActivity(SetupActivity.class);
}
if (menuItem.getItemId() == R.id.settings) {
return startActivity(SettingsActivity.class);
}
final var intent = menuItem.getIntent();
if (intent == null) {
return false;
}
setChatFilter(Intents.toChatFilter(intent));
return true;
}
private boolean startActivity(final Class<? extends AppCompatActivity> activityClazz) {
startActivity(new Intent(requireContext(), activityClazz));
binding.drawerLayout.close();
return false;
}
private void setChatFilter(final ChatFilter chatFilter) {
overviewViewModel.setChatFilter(chatFilter);
binding.drawerLayout.close();

View file

@ -0,0 +1,14 @@
package im.conversations.android.ui.fragment.settings;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceFragmentCompat;
import im.conversations.android.R;
public class MainSettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
setPreferencesFromResource(R.xml.preferences_main, rootKey);
}
}

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M21.5,14.98c-0.02,0 -0.03,0 -0.05,0.01C21.2,13.3 19.76,12 18,12c-1.4,0 -2.6,0.83 -3.16,2.02C13.26,14.1 12,15.4 12,17c0,1.66 1.34,3 3,3l6.5,-0.02c1.38,0 2.5,-1.12 2.5,-2.5S22.88,14.98 21.5,14.98zM10,4.26v2.09C7.67,7.18 6,9.39 6,12c0,1.77 0.78,3.34 2,4.44V14h2v6H4v-2h2.73C5.06,16.54 4,14.4 4,12C4,8.27 6.55,5.15 10,4.26zM20,6h-2.73c1.43,1.26 2.41,3.01 2.66,5l-2.02,0C17.68,9.64 16.98,8.45 16,7.56V10h-2V4h6V6z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.49,2 2,6.49 2,12s4.49,10 10,10c1.38,0 2.5,-1.12 2.5,-2.5c0,-0.61 -0.23,-1.2 -0.64,-1.67c-0.08,-0.1 -0.13,-0.21 -0.13,-0.33c0,-0.28 0.22,-0.5 0.5,-0.5H16c3.31,0 6,-2.69 6,-6C22,6.04 17.51,2 12,2zM17.5,13c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5C19,12.33 18.33,13 17.5,13zM14.5,9C13.67,9 13,8.33 13,7.5C13,6.67 13.67,6 14.5,6S16,6.67 16,7.5C16,8.33 15.33,9 14.5,9zM5,11.5C5,10.67 5.67,10 6.5,10S8,10.67 8,11.5C8,12.33 7.33,13 6.5,13S5,12.33 5,11.5zM11,7.5C11,8.33 10.33,9 9.5,9S8,8.33 8,7.5C8,6.67 8.67,6 9.5,6S11,6.67 11,7.5z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12 5.16,-1.26 9,-6.45 9,-12L21,5l-9,-4zM12,11.99h7c-0.53,4.12 -3.28,7.79 -7,8.94L12,12L5,12L5,6.3l7,-3.11v8.8z" />
</vector>

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2019 Daniel Gultsch
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="false"
app:elevation="0dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/material_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/title_activity_settings"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View file

@ -13,6 +13,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/searchbar_scrolling_view_behavior"/>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
@ -29,6 +34,15 @@
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/extended_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_gravity="bottom|end"
android:text="@string/start_chat"
app:icon="@drawable/ic_chat_24dp"/>
<com.google.android.material.search.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
@ -38,14 +52,6 @@
app:useDrawerArrowDrawable="true">
<!-- Search suggestions/results go here (ScrollView, RecyclerView, etc.). -->
</com.google.android.material.search.SearchView>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/extended_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_gravity="bottom|end"
android:text="@string/start_chat"
app:icon="@drawable/ic_chat_24dp"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1017,5 +1017,10 @@
<string name="accounts">Accounts</string>
<string name="spaces">Spaces</string>
<string name="chats">Chats</string>
<string name="pref_title_appearance">Appearance</string>
<string name="pref_summary_appearance"><![CDATA[Theme & Colors]]></string>
<string name="pref_title_security">Security</string>
<string name="pref_summary_security">Encryption, Blind Trust Before Verification, MIM Detection</string>
<string name="unified_push_summary">Notification relay for UnifiedPush compatible third party apps</string>
</resources>

View file

@ -27,5 +27,6 @@
<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_light_inversePrimary</item>
<item name="android:statusBarColor">?colorSurface</item>
</style>
</resources>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
app:title="@string/pref_title_appearance"
app:summary="@string/pref_summary_appearance"
android:icon="@drawable/ic_palette_24dp"
app:fragment="im.conversations.android.ui.fragment.MainSettingsFragment"/>
<Preference
app:title="@string/pref_title_security"
app:summary="@string/pref_summary_security"
android:icon="@drawable/ic_security_24dp"
app:fragment="im.conversations.android.ui.fragment.MainSettingsFragment"/>
<Preference
app:title="@string/unified_push_distributor"
app:summary="@string/unified_push_summary"
android:icon="@drawable/ic_cloud_sync_24dp"
app:fragment="im.conversations.android.ui.fragment.MainSettingsFragment"/>
</PreferenceScreen>

View file

@ -5,6 +5,7 @@ buildscript {
lifecycleVersion = "2.2.0"
navVersion = '2.5.3'
roomVersion = "2.5.0"
preferenceVersion = "1.2.0"
espressoVersion = "3.5.1"
}