diff --git a/app/build.gradle b/app/build.gradle
index 80fae7a4..fd963943 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -41,6 +41,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta5'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
+ implementation 'androidx.preference:preference:1.1.0-rc01'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index eefcbdad..314b2b1e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -41,6 +41,10 @@
android:name=".log.LogsActivity"
android:label="@string/title_activity_logs"
android:theme="@style/AppTheme.NoActionBar" />
+
diff --git a/app/src/main/java/com/github/gotify/init/InitializationActivity.java b/app/src/main/java/com/github/gotify/init/InitializationActivity.java
index 2e8df5c6..b43b067b 100644
--- a/app/src/main/java/com/github/gotify/init/InitializationActivity.java
+++ b/app/src/main/java/com/github/gotify/init/InitializationActivity.java
@@ -8,6 +8,7 @@
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.preference.PreferenceManager;
import com.github.gotify.NotificationSupport;
import com.github.gotify.R;
import com.github.gotify.Settings;
@@ -21,6 +22,7 @@
import com.github.gotify.login.LoginActivity;
import com.github.gotify.messages.MessagesActivity;
import com.github.gotify.service.WebSocketService;
+import com.github.gotify.settings.ThemeHelper;
import static com.github.gotify.api.Callback.callInUI;
@@ -31,6 +33,13 @@ public class InitializationActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.init(this);
+ String theme =
+ PreferenceManager.getDefaultSharedPreferences(this)
+ .getString(
+ getString(R.string.setting_key_theme),
+ getString(R.string.theme_default));
+ ThemeHelper.setTheme(this, theme);
+
setContentView(R.layout.splash);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
diff --git a/app/src/main/java/com/github/gotify/login/LoginActivity.java b/app/src/main/java/com/github/gotify/login/LoginActivity.java
index 235d96fd..a57f2737 100644
--- a/app/src/main/java/com/github/gotify/login/LoginActivity.java
+++ b/app/src/main/java/com/github/gotify/login/LoginActivity.java
@@ -14,6 +14,7 @@
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.view.ContextThemeWrapper;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
@@ -135,7 +136,7 @@ public void doCheckUrl() {
}
public void showHttpWarning() {
- new AlertDialog.Builder(this)
+ new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme_Dialog))
.setTitle(R.string.warning)
.setCancelable(true)
.setMessage(R.string.http_warning)
@@ -273,7 +274,7 @@ private void newClientDialog(ApiClient client) {
EditText clientName = new EditText(this);
clientName.setText(Build.MODEL);
- new AlertDialog.Builder(this)
+ new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme_Dialog))
.setTitle(R.string.create_client_title)
.setMessage(R.string.create_client_message)
.setView(clientName)
diff --git a/app/src/main/java/com/github/gotify/messages/MessagesActivity.java b/app/src/main/java/com/github/gotify/messages/MessagesActivity.java
index 4ce3bc5c..3522dd54 100644
--- a/app/src/main/java/com/github/gotify/messages/MessagesActivity.java
+++ b/app/src/main/java/com/github/gotify/messages/MessagesActivity.java
@@ -22,6 +22,7 @@
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
@@ -61,6 +62,7 @@
import com.github.gotify.messages.provider.MessageWithImage;
import com.github.gotify.picasso.PicassoDataRequestHandler;
import com.github.gotify.service.WebSocketService;
+import com.github.gotify.settings.SettingsActivity;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
@@ -309,7 +311,7 @@ public boolean onNavigationItemSelected(MenuItem item) {
startLoading();
toolbar.setSubtitle("");
} else if (id == R.id.logout) {
- new AlertDialog.Builder(this)
+ new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme_Dialog))
.setTitle(R.string.logout)
.setMessage(getString(R.string.logout_confirm))
.setPositiveButton(R.string.yes, this::doLogout)
@@ -317,6 +319,8 @@ public boolean onNavigationItemSelected(MenuItem item) {
.show();
} else if (id == R.id.nav_logs) {
startActivity(new Intent(this, LogsActivity.class));
+ } else if (id == R.id.settings) {
+ startActivity(new Intent(this, SettingsActivity.class));
}
drawer.closeDrawer(GravityCompat.START);
@@ -326,6 +330,7 @@ public boolean onNavigationItemSelected(MenuItem item) {
public void doLogout(DialogInterface dialog, int which) {
setContentView(R.layout.splash);
new DeleteClientAndNavigateToLogin().execute();
+ finish();
}
private void startLoading() {
diff --git a/app/src/main/java/com/github/gotify/settings/SettingsActivity.java b/app/src/main/java/com/github/gotify/settings/SettingsActivity.java
new file mode 100644
index 00000000..b7340792
--- /dev/null
+++ b/app/src/main/java/com/github/gotify/settings/SettingsActivity.java
@@ -0,0 +1,56 @@
+package com.github.gotify.settings;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.MenuItem;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceManager;
+import com.github.gotify.R;
+
+public class SettingsActivity extends AppCompatActivity
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.settings_activity);
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.settings, new SettingsFragment())
+ .commit();
+ setSupportActionBar(findViewById(R.id.toolbar));
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowCustomEnabled(true);
+ }
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+ sharedPreferences.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (getString(R.string.setting_key_theme).equals(key)) {
+ ThemeHelper.setTheme(
+ this, sharedPreferences.getString(key, getString(R.string.theme_default)));
+ }
+ }
+
+ public static class SettingsFragment extends PreferenceFragmentCompat {
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ setPreferencesFromResource(R.xml.root_preferences, rootKey);
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/gotify/settings/ThemeHelper.java b/app/src/main/java/com/github/gotify/settings/ThemeHelper.java
new file mode 100644
index 00000000..58af750c
--- /dev/null
+++ b/app/src/main/java/com/github/gotify/settings/ThemeHelper.java
@@ -0,0 +1,27 @@
+package com.github.gotify.settings;
+
+import android.content.Context;
+import android.os.Build;
+import androidx.appcompat.app.AppCompatDelegate;
+import com.github.gotify.R;
+
+public final class ThemeHelper {
+ private ThemeHelper() {}
+
+ public static void setTheme(Context context, String newTheme) {
+ AppCompatDelegate.setDefaultNightMode(ofKey(context, newTheme));
+ }
+
+ private static int ofKey(Context context, String newTheme) {
+ if (context.getString(R.string.theme_dark).equals(newTheme)) {
+ return AppCompatDelegate.MODE_NIGHT_YES;
+ }
+ if (context.getString(R.string.theme_light).equals(newTheme)) {
+ return AppCompatDelegate.MODE_NIGHT_NO;
+ }
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
+ return AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY;
+ }
+ return AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
+ }
+}
diff --git a/app/src/main/res/drawable/gradient.xml b/app/src/main/res/drawable/gradient.xml
deleted file mode 100644
index 5f41b34e..00000000
--- a/app/src/main/res/drawable/gradient.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml
index 4522aca8..a087c86c 100644
--- a/app/src/main/res/drawable/ic_settings.xml
+++ b/app/src/main/res/drawable/ic_settings.xml
@@ -1,4 +1,6 @@
-
+
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index 16565ace..1ce90e87 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -6,22 +6,22 @@
android:layout_height="match_parent"
android:fillViewport="true">
-
diff --git a/app/src/main/res/layout/activity_messages.xml b/app/src/main/res/layout/activity_messages.xml
index 8dfd48ee..fef81662 100644
--- a/app/src/main/res/layout/activity_messages.xml
+++ b/app/src/main/res/layout/activity_messages.xml
@@ -91,6 +91,7 @@
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
+ app:theme="@style/AppTheme.Nav"
app:headerLayout="@layout/nav_header_drawer"
app:menu="@menu/messages_menu" />
diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml
new file mode 100644
index 00000000..caf07a74
--- /dev/null
+++ b/app/src/main/res/layout/settings_activity.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/messages_menu.xml b/app/src/main/res/menu/messages_menu.xml
index 650b683a..28241bfb 100644
--- a/app/src/main/res/menu/messages_menu.xml
+++ b/app/src/main/res/menu/messages_menu.xml
@@ -16,15 +16,20 @@
+ android:id="@+id/settings"
+ android:title="@string/title_activity_settings" />
+
diff --git a/app/src/main/res/values-notnight/colors.xml b/app/src/main/res/values-notnight/colors.xml
new file mode 100644
index 00000000..59e1f26c
--- /dev/null
+++ b/app/src/main/res/values-notnight/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #3F51B5
+ #000000
+ #3867d6
+ #1c49b4
+ #434343
+ #E74C3C
+ #FFFFFF
+
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
new file mode 100644
index 00000000..888606ac
--- /dev/null
+++ b/app/src/main/res/values/arrays.xml
@@ -0,0 +1,10 @@
+
+
+ - @string/theme_light
+ - @string/theme_dark
+ - @string/theme_default
+
+ Light
+ Dark
+ System Default
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 0181dbcf..0d377101 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,9 +1,10 @@
#3F51B5
+ #FFFFFF
#3867d6
#1c49b4
- #434343
+ #797979
#E74C3C
#FFFFFF
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0d95ce0b..34487045 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -64,4 +64,8 @@
Waiting for network
%s@%s
There are no messages, yet.\nSend a message to Gotify\nand it will appear here.
+ Settings
+ Appearance
+ Theme
+ theme
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 545b9c6d..775c7066 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,20 +1,27 @@
-
+
-
+
+
+
-
+
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
new file mode 100644
index 00000000..0ff1dbea
--- /dev/null
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+