diff --git a/opencloudApp/src/androidTest/java/eu/opencloud/android/settings/SettingsFragmentTest.kt b/opencloudApp/src/androidTest/java/eu/opencloud/android/settings/SettingsFragmentTest.kt index 20407c6947..67dc4e1e9d 100644 --- a/opencloudApp/src/androidTest/java/eu/opencloud/android/settings/SettingsFragmentTest.kt +++ b/opencloudApp/src/androidTest/java/eu/opencloud/android/settings/SettingsFragmentTest.kt @@ -22,9 +22,12 @@ package eu.opencloud.android.settings import android.content.ClipboardManager import android.content.Context +import androidx.appcompat.app.AppCompatDelegate import androidx.fragment.app.testing.FragmentScenario import androidx.fragment.app.testing.launchFragmentInContainer +import androidx.preference.ListPreference import androidx.preference.Preference +import androidx.preference.PreferenceManager import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches @@ -38,9 +41,11 @@ import eu.opencloud.android.R import eu.opencloud.android.presentation.releasenotes.ReleaseNotesActivity import eu.opencloud.android.presentation.settings.privacypolicy.PrivacyPolicyActivity import eu.opencloud.android.presentation.settings.SettingsFragment +import eu.opencloud.android.presentation.settings.AppearanceMode import eu.opencloud.android.presentation.releasenotes.ReleaseNotesViewModel import eu.opencloud.android.presentation.settings.more.SettingsMoreViewModel import eu.opencloud.android.presentation.settings.SettingsViewModel +import eu.opencloud.android.providers.WorkManagerProvider import eu.opencloud.android.utils.matchers.verifyPreference import eu.opencloud.android.utils.releaseNotesList import io.mockk.every @@ -61,6 +66,7 @@ class SettingsFragmentTest { private lateinit var fragmentScenario: FragmentScenario private var subsectionSecurity: Preference? = null + private var prefAppearance: ListPreference? = null private var subsectionLogging: Preference? = null private var subsectionPictureUploads: Preference? = null private var subsectionVideoUploads: Preference? = null @@ -75,10 +81,16 @@ class SettingsFragmentTest { private lateinit var context: Context private lateinit var version: String + private var previousNightMode = AppCompatDelegate.MODE_NIGHT_UNSPECIFIED + private var previousAppearance: String? = null @Before fun setUp() { context = InstrumentationRegistry.getInstrumentation().targetContext + previousNightMode = AppCompatDelegate.getDefaultNightMode() + previousAppearance = PreferenceManager.getDefaultSharedPreferences(context) + .getString(AppearanceMode.PREFERENCE_KEY, null) + PreferenceManager.getDefaultSharedPreferences(context).edit().remove(AppearanceMode.PREFERENCE_KEY).commit() settingsViewModel = mockk(relaxed = true) moreViewModel = mockk(relaxed = true) releaseNotesViewModel = mockk(relaxed = true) @@ -90,6 +102,7 @@ class SettingsFragmentTest { allowOverride(override = true) modules( module { + single { mockk(relaxed = true) } viewModel { settingsViewModel } @@ -116,6 +129,14 @@ class SettingsFragmentTest { @After fun tearDown() { + if (::fragmentScenario.isInitialized) { + fragmentScenario.close() + } + PreferenceManager.getDefaultSharedPreferences(context).edit() + .putString(AppearanceMode.PREFERENCE_KEY, previousAppearance).commit() + InstrumentationRegistry.getInstrumentation().runOnMainSync { + AppCompatDelegate.setDefaultNightMode(previousNightMode) + } Intents.release() unmockkAll() } @@ -134,6 +155,7 @@ class SettingsFragmentTest { fragmentScenario = launchFragmentInContainer(themeResId = R.style.Theme_openCloud) fragmentScenario.onFragment { fragment -> subsectionSecurity = fragment.findPreference(SUBSECTION_SECURITY) + prefAppearance = fragment.findPreference(AppearanceMode.PREFERENCE_KEY) subsectionLogging = fragment.findPreference(SUBSECTION_LOGGING) subsectionPictureUploads = fragment.findPreference(SUBSECTION_PICTURE_UPLOADS) subsectionVideoUploads = fragment.findPreference(SUBSECTION_VIDEO_UPLOADS) @@ -148,6 +170,24 @@ class SettingsFragmentTest { fun settingsViewCommon() { launchTest(attachedAccount = false) + assertEquals( + listOf( + context.getString(R.string.prefs_appearance_system), + context.getString(R.string.prefs_appearance_light), + context.getString(R.string.prefs_appearance_dark) + ), + prefAppearance?.entries?.toList() + ) + assertEquals(AppearanceMode.entries.map { it.name }, prefAppearance?.entryValues?.map { it.toString() }) + assertEquals(AppearanceMode.SYSTEM.name, prefAppearance?.value) + prefAppearance?.verifyPreference( + keyPref = AppearanceMode.PREFERENCE_KEY, + titlePref = context.getString(R.string.prefs_appearance), + summaryPref = context.getString(R.string.prefs_appearance_system), + visible = true, + enabled = true + ) + subsectionSecurity?.verifyPreference( keyPref = SUBSECTION_SECURITY, titlePref = context.getString(R.string.prefs_subsection_security), @@ -195,6 +235,51 @@ class SettingsFragmentTest { ) } + @Test + fun invalidAppearanceModeIsNormalizedToSystem() { + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putString(AppearanceMode.PREFERENCE_KEY, "INVALID") + .commit() + + launchTest(attachedAccount = false) + + assertEquals(AppearanceMode.SYSTEM.name, prefAppearance?.value) + assertEquals(context.getString(R.string.prefs_appearance_system), prefAppearance?.summary) + assertEquals( + AppearanceMode.SYSTEM.name, + PreferenceManager.getDefaultSharedPreferences(context) + .getString(AppearanceMode.PREFERENCE_KEY, null) + ) + } + + @Test + fun appearanceSelectionAppliesAndPersistsNightMode() { + launchTest(attachedAccount = false) + + listOf( + AppearanceMode.LIGHT to R.string.prefs_appearance_light, + AppearanceMode.DARK to R.string.prefs_appearance_dark, + AppearanceMode.SYSTEM to R.string.prefs_appearance_system + ).forEach { (mode, label) -> + onView(withText(R.string.prefs_appearance)).perform(click()) + onView(withText(label)).perform(click()) + + assertEquals(mode.nightMode, AppCompatDelegate.getDefaultNightMode()) + assertEquals( + mode.name, + PreferenceManager.getDefaultSharedPreferences(context) + .getString(AppearanceMode.PREFERENCE_KEY, null) + ) + fragmentScenario.recreate() + fragmentScenario.onFragment { fragment -> + val preference = fragment.findPreference(AppearanceMode.PREFERENCE_KEY) + assertEquals(mode.name, preference?.value) + assertEquals(context.getString(label), preference?.summary) + } + } + } + @Test fun settingsViewNoAccountAttached() { launchTest(attachedAccount = false) diff --git a/opencloudApp/src/androidTest/java/eu/opencloud/android/ui/ListSelectorTest.kt b/opencloudApp/src/androidTest/java/eu/opencloud/android/ui/ListSelectorTest.kt new file mode 100644 index 0000000000..278fc352c0 --- /dev/null +++ b/opencloudApp/src/androidTest/java/eu/opencloud/android/ui/ListSelectorTest.kt @@ -0,0 +1,110 @@ +/** + * openCloud Android client application + * + * Copyright (C) 2026 openCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * 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 . + */ + +package eu.opencloud.android.ui + +import android.content.Context +import android.content.res.Configuration +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.StateListDrawable +import android.view.LayoutInflater +import android.widget.ImageView +import android.widget.TextView +import androidx.appcompat.view.ContextThemeWrapper +import androidx.core.graphics.ColorUtils +import androidx.test.platform.app.InstrumentationRegistry +import eu.opencloud.android.R +import eu.opencloud.android.presentation.common.BottomSheetFragmentItemView +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue +import org.junit.Test + +class ListSelectorTest { + + @Test + fun selectorLoadsWithoutThemeInLightAndDarkModes() { + for (nightMode in listOf(Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_YES)) { + val context = contextForNightMode(nightMode) + val selector = context.resources.getDrawable(R.drawable.list_selector, null) as StateListDrawable + // Remove the transition so the current drawable can be checked immediately. + selector.setExitFadeDuration(0) + for (state in listOf(intArrayOf(), intArrayOf(android.R.attr.state_pressed), intArrayOf(android.R.attr.state_focused))) { + selector.state = state + val expectedColor = if (state.isEmpty()) R.color.theme_color_background else R.color.theme_color_selection + assertEquals(context.getColor(expectedColor), (selector.current as ColorDrawable).color) + } + } + } + + @Test + fun gridRowsInflateInLightAndDarkModes() { + assertRowInflates(R.layout.grid_item) + } + + @Test + fun uploadRowsInflateInLightAndDarkModes() { + assertRowInflates(R.layout.uploader_list_item_layout) + } + + @Test + fun selectedSortRowStaysReadableInLightAndDarkModes() { + InstrumentationRegistry.getInstrumentation().runOnMainSync { + for (nightMode in listOf(Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_YES)) { + val context = ContextThemeWrapper(contextForNightMode(nightMode), R.style.Theme_openCloud) + val sheet = LayoutInflater.from(context).inflate(R.layout.sort_bottom_sheet_fragment, null) + val row = sheet.findViewById(R.id.sort_by_name) + row.setSelected(R.drawable.ic_baseline_arrow_upward) + val textColor = row.findViewById(R.id.item_title).currentTextColor + assertTrue(ColorUtils.calculateContrast(textColor, context.getColor(R.color.theme_color_surface)) >= 4.5) + } + } + } + + @Test + fun gridSharingIndicatorsUseReadableTintsInLightAndDarkModes() { + InstrumentationRegistry.getInstrumentation().runOnMainSync { + for (nightMode in listOf(Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_YES)) { + val context = ContextThemeWrapper(contextForNightMode(nightMode), R.style.Theme_openCloud) + val row = LayoutInflater.from(context).inflate(R.layout.grid_item, null) + for (id in listOf(R.id.shared_via_users_icon, R.id.shared_by_link_icon)) { + val tint = row.findViewById(id).imageTintList + assertNotNull(tint) + assertTrue(ColorUtils.calculateContrast(tint!!.defaultColor, context.getColor(R.color.theme_color_surface)) >= 3.0) + } + } + } + } + + private fun assertRowInflates(layout: Int) { + InstrumentationRegistry.getInstrumentation().runOnMainSync { + for (nightMode in listOf(Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_YES)) { + val context = ContextThemeWrapper(contextForNightMode(nightMode), R.style.Theme_openCloud) + assertNotNull(LayoutInflater.from(context).inflate(layout, null).background) + } + } + } + + private fun contextForNightMode(nightMode: Int): Context { + val context = InstrumentationRegistry.getInstrumentation().targetContext + val configuration = Configuration(context.resources.configuration).apply { + uiMode = (uiMode and Configuration.UI_MODE_NIGHT_MASK.inv()) or nightMode + } + return context.createConfigurationContext(configuration) + } +} diff --git a/opencloudApp/src/main/java/eu/opencloud/android/MainApp.kt b/opencloudApp/src/main/java/eu/opencloud/android/MainApp.kt index 1a87639d88..a610a8a7a8 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/MainApp.kt +++ b/opencloudApp/src/main/java/eu/opencloud/android/MainApp.kt @@ -37,6 +37,7 @@ import android.os.Bundle import android.view.WindowManager import android.widget.CheckBox import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.pm.PackageInfoCompat import eu.opencloud.android.data.providers.implementation.OCSharedPreferencesProvider @@ -64,6 +65,7 @@ import eu.opencloud.android.presentation.security.passcode.PassCodeManager import eu.opencloud.android.presentation.security.pattern.PatternActivity import eu.opencloud.android.presentation.security.pattern.PatternManager import eu.opencloud.android.presentation.settings.logging.SettingsLogsFragment.Companion.PREFERENCE_ENABLE_LOGGING +import eu.opencloud.android.presentation.settings.AppearanceMode import eu.opencloud.android.providers.CoroutinesDispatcherProvider import eu.opencloud.android.providers.LogsProvider import eu.opencloud.android.providers.MdmProvider @@ -103,6 +105,14 @@ class MainApp : Application() { appContext = applicationContext + val appearancePreferences = androidx.preference.PreferenceManager.getDefaultSharedPreferences(appContext) + val storedAppearanceMode = appearancePreferences.getString(AppearanceMode.PREFERENCE_KEY, null) + val appearanceMode = AppearanceMode.fromPreferenceValue(storedAppearanceMode) + if (storedAppearanceMode != appearanceMode.name) { + appearancePreferences.edit().putString(AppearanceMode.PREFERENCE_KEY, appearanceMode.name).apply() + } + AppCompatDelegate.setDefaultNightMode(appearanceMode.nightMode) + // Ensure Logcat shows Timber logs in debug builds if (BuildConfig.DEBUG) { try { diff --git a/opencloudApp/src/main/java/eu/opencloud/android/extensions/ActivityExt.kt b/opencloudApp/src/main/java/eu/opencloud/android/extensions/ActivityExt.kt index 2c9a6171bf..38559d812a 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/extensions/ActivityExt.kt +++ b/opencloudApp/src/main/java/eu/opencloud/android/extensions/ActivityExt.kt @@ -368,7 +368,7 @@ fun Activity.openFeedbackDialog() { val getInContactDescriptionTextView = TextView(this).apply { text = spannableString - setTextColor(getColor(android.R.color.black)) + setTextColor(getColor(R.color.theme_color_on_surface)) setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) movementMethod = LinkMovementMethod.getInstance() } diff --git a/opencloudApp/src/main/java/eu/opencloud/android/presentation/accounts/ManageAccountsDialogFragment.kt b/opencloudApp/src/main/java/eu/opencloud/android/presentation/accounts/ManageAccountsDialogFragment.kt index d471b22b20..f50f50cc31 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/presentation/accounts/ManageAccountsDialogFragment.kt +++ b/opencloudApp/src/main/java/eu/opencloud/android/presentation/accounts/ManageAccountsDialogFragment.kt @@ -25,18 +25,17 @@ import android.accounts.Account import android.accounts.AccountManager import android.accounts.AccountManagerFuture import android.accounts.OperationCanceledException -import android.app.AlertDialog import android.app.Dialog import android.content.Intent import android.os.Bundle import android.security.KeyChain -import android.view.ContextThemeWrapper import android.view.View import android.widget.ImageView import android.widget.LinearLayout import android.widget.PopupMenu import android.widget.ProgressBar import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import androidx.fragment.app.DialogFragment import androidx.recyclerview.widget.LinearLayoutManager @@ -79,7 +78,7 @@ class ManageAccountsDialogFragment : DialogFragment(), ManageAccountsAdapter.Acc } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val builder = AlertDialog.Builder(ContextThemeWrapper(requireContext(), R.style.Theme_AppCompat_Dialog_Alert)) + val builder = AlertDialog.Builder(requireContext()) val inflater = this.layoutInflater dialogView = inflater.inflate(R.layout.manage_accounts_dialog, null) builder.setView(dialogView) diff --git a/opencloudApp/src/main/java/eu/opencloud/android/presentation/common/BottomSheetFragmentItemView.kt b/opencloudApp/src/main/java/eu/opencloud/android/presentation/common/BottomSheetFragmentItemView.kt index 0ae8c0d762..5e61e25250 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/presentation/common/BottomSheetFragmentItemView.kt +++ b/opencloudApp/src/main/java/eu/opencloud/android/presentation/common/BottomSheetFragmentItemView.kt @@ -73,7 +73,7 @@ class BottomSheetFragmentItemView @JvmOverloads constructor( fun setSelected(iconAdditional: Int) { itemAdditionalIcon = ContextCompat.getDrawable(context, iconAdditional) - val selectedColor = ContextCompat.getColor(context, R.color.primary) + val selectedColor = ContextCompat.getColor(context, R.color.theme_color_selected_foreground) binding.itemIcon.setColorFilter(selectedColor) binding.itemTitle.setTextColor(selectedColor) binding.itemAdditionalIcon.setColorFilter(selectedColor) diff --git a/opencloudApp/src/main/java/eu/opencloud/android/presentation/files/filelist/FileListAdapter.kt b/opencloudApp/src/main/java/eu/opencloud/android/presentation/files/filelist/FileListAdapter.kt index b7a9b2e5ea..69bebe0d83 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/presentation/files/filelist/FileListAdapter.kt +++ b/opencloudApp/src/main/java/eu/opencloud/android/presentation/files/filelist/FileListAdapter.kt @@ -32,7 +32,6 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout -import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView @@ -64,6 +63,24 @@ class FileListAdapter( private var fileListOption: FileListOption = FileListOption.ALL_FILES private val disallowTouchesWithOtherWindows = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context) + private val colorSurface by lazy { + context.obtainStyledAttributes(intArrayOf(R.attr.colorSurface)).run { + try { + getColor(0, Color.TRANSPARENT) + } finally { + recycle() + } + } + } + private val colorSelection by lazy { + context.obtainStyledAttributes(intArrayOf(R.attr.colorSelection)).run { + try { + getColor(0, Color.TRANSPARENT) + } finally { + recycle() + } + } + } init { setHasStableIds(true) @@ -255,17 +272,15 @@ class FileListAdapter( position = adapterPosition ) } - holder.itemView.setBackgroundColor(Color.WHITE) - val checkBoxV = holder.itemView.findViewById(R.id.custom_checkbox).apply { isVisible = hasActiveSelection } if (isSelected(position)) { - holder.itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.selected_item_background)) + holder.itemView.setBackgroundColor(colorSelection) checkBoxV.setImageResource(R.drawable.ic_checkbox_marked) } else { - holder.itemView.setBackgroundColor(Color.WHITE) + holder.itemView.setBackgroundColor(colorSurface) checkBoxV.setImageResource(R.drawable.ic_checkbox_blank_outline) } @@ -292,7 +307,7 @@ class FileListAdapter( } if (file.mimeType.equals("image/png", ignoreCase = true)) { - fileIcon.setBackgroundColor(ContextCompat.getColor(context, R.color.background_color)) + fileIcon.setBackgroundColor(colorSurface) } else { fileIcon.setBackgroundColor(Color.TRANSPARENT) } diff --git a/opencloudApp/src/main/java/eu/opencloud/android/presentation/settings/AppearanceMode.kt b/opencloudApp/src/main/java/eu/opencloud/android/presentation/settings/AppearanceMode.kt new file mode 100644 index 0000000000..f246e68009 --- /dev/null +++ b/opencloudApp/src/main/java/eu/opencloud/android/presentation/settings/AppearanceMode.kt @@ -0,0 +1,33 @@ +/** + * openCloud Android client application + * + * Copyright (C) 2026 openCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * 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 . + */ + +package eu.opencloud.android.presentation.settings + +import androidx.appcompat.app.AppCompatDelegate + +enum class AppearanceMode(val nightMode: Int) { + SYSTEM(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM), + LIGHT(AppCompatDelegate.MODE_NIGHT_NO), + DARK(AppCompatDelegate.MODE_NIGHT_YES); + + companion object { + const val PREFERENCE_KEY = "appearance_mode" + + fun fromPreferenceValue(value: String?) = entries.firstOrNull { it.name == value } ?: SYSTEM + } +} diff --git a/opencloudApp/src/main/java/eu/opencloud/android/presentation/settings/SettingsFragment.kt b/opencloudApp/src/main/java/eu/opencloud/android/presentation/settings/SettingsFragment.kt index c5e390fd09..35ea457697 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/presentation/settings/SettingsFragment.kt +++ b/opencloudApp/src/main/java/eu/opencloud/android/presentation/settings/SettingsFragment.kt @@ -27,6 +27,8 @@ import android.content.Intent import android.os.Build import android.os.Bundle import android.provider.Settings +import androidx.appcompat.app.AppCompatDelegate +import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceScreen @@ -47,6 +49,7 @@ class SettingsFragment : PreferenceFragmentCompat() { private val releaseNotesViewModel by viewModel() private var settingsScreen: PreferenceScreen? = null + private var prefAppearance: ListPreference? = null private var subsectionPictureUploads: Preference? = null private var subsectionVideoUploads: Preference? = null private var subsectionMore: Preference? = null @@ -59,6 +62,22 @@ class SettingsFragment : PreferenceFragmentCompat() { setPreferencesFromResource(R.xml.settings, rootKey) settingsScreen = findPreference(SCREEN_SETTINGS) + prefAppearance = findPreference(AppearanceMode.PREFERENCE_KEY)?.apply { + entries = arrayOf( + getString(R.string.prefs_appearance_system), + getString(R.string.prefs_appearance_light), + getString(R.string.prefs_appearance_dark) + ) + entryValues = AppearanceMode.entries.map { it.name }.toTypedArray() + value = AppearanceMode.fromPreferenceValue(value).name + summary = entry + setOnPreferenceChangeListener { preference, newValue -> + val appearanceMode = AppearanceMode.fromPreferenceValue(newValue as String) + preference.summary = entries[findIndexOfValue(appearanceMode.name)] + AppCompatDelegate.setDefaultNightMode(appearanceMode.nightMode) + true + } + } subsectionPictureUploads = findPreference(SUBSECTION_PICTURE_UPLOADS) subsectionVideoUploads = findPreference(SUBSECTION_VIDEO_UPLOADS) subsectionMore = findPreference(SUBSECTION_MORE) diff --git a/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/CopyToClipboardActivity.java b/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/CopyToClipboardActivity.java index c4082b85e2..f3fd52c166 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/CopyToClipboardActivity.java +++ b/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/CopyToClipboardActivity.java @@ -19,13 +19,14 @@ package eu.opencloud.android.ui.activity; -import android.app.Activity; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Intent; import android.os.Bundle; import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity; + import eu.opencloud.android.R; import timber.log.Timber; @@ -33,7 +34,7 @@ * Activity copying the text of the received Intent into the system clipboard. */ @SuppressWarnings("deprecation") -public class CopyToClipboardActivity extends Activity { +public class CopyToClipboardActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { diff --git a/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/FileDisplayActivity.kt b/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/FileDisplayActivity.kt index a4c9c95f16..9515048ae1 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/FileDisplayActivity.kt +++ b/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/FileDisplayActivity.kt @@ -1449,13 +1449,13 @@ class FileDisplayActivity : FileActivity(), val messageTextView = TextView(this).apply { text = message setPadding(0, 70, 0, 30) - setTextColor(ContextCompat.getColor(this@FileDisplayActivity, android.R.color.black)) + setTextColor(ContextCompat.getColor(this@FileDisplayActivity, R.color.theme_color_on_surface)) setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) } val urlTextView = TextView(this).apply { text = urlFormat - setTextColor(ContextCompat.getColor(this@FileDisplayActivity, android.R.color.black)) + setTextColor(ContextCompat.getColor(this@FileDisplayActivity, R.color.theme_color_on_surface)) setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) } val scrollView = ScrollView(this).apply { diff --git a/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/WhatsNewActivity.java b/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/WhatsNewActivity.java index 79beee1bec..29a39e03c7 100644 --- a/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/WhatsNewActivity.java +++ b/opencloudApp/src/main/java/eu/opencloud/android/ui/activity/WhatsNewActivity.java @@ -36,9 +36,9 @@ import android.widget.TextView; import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; import androidx.core.view.ViewKt; import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; import androidx.viewpager.widget.ViewPager; @@ -56,7 +56,7 @@ /** * @author Bartosz Przybylski */ -public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPageChangeListener { +public class WhatsNewActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener { private ImageButton mForwardFinishButton; private ProgressIndicator mProgress; diff --git a/opencloudApp/src/main/res/color/dialog_button_text.xml b/opencloudApp/src/main/res/color/dialog_button_text.xml new file mode 100644 index 0000000000..1ca3c2d342 --- /dev/null +++ b/opencloudApp/src/main/res/color/dialog_button_text.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/opencloudApp/src/main/res/drawable/ic_appearance.xml b/opencloudApp/src/main/res/drawable/ic_appearance.xml new file mode 100644 index 0000000000..2eaddbe043 --- /dev/null +++ b/opencloudApp/src/main/res/drawable/ic_appearance.xml @@ -0,0 +1,10 @@ + + + diff --git a/opencloudApp/src/main/res/drawable/ic_spaces_placeholder.xml b/opencloudApp/src/main/res/drawable/ic_spaces_placeholder.xml index 91975e389a..a46199225c 100644 --- a/opencloudApp/src/main/res/drawable/ic_spaces_placeholder.xml +++ b/opencloudApp/src/main/res/drawable/ic_spaces_placeholder.xml @@ -5,6 +5,6 @@ android:pivotY="12" android:scaleX="0.25" android:scaleY="0.25"> - + diff --git a/opencloudApp/src/main/res/drawable/list_selector.xml b/opencloudApp/src/main/res/drawable/list_selector.xml index af7ce4b6f4..f532a8bb09 100644 --- a/opencloudApp/src/main/res/drawable/list_selector.xml +++ b/opencloudApp/src/main/res/drawable/list_selector.xml @@ -20,8 +20,8 @@ - - - + + + diff --git a/opencloudApp/src/main/res/drawable/numberkeyboard_key_bg_pressed.xml b/opencloudApp/src/main/res/drawable/numberkeyboard_key_bg_pressed.xml index 3c6edc4831..586b386e44 100644 --- a/opencloudApp/src/main/res/drawable/numberkeyboard_key_bg_pressed.xml +++ b/opencloudApp/src/main/res/drawable/numberkeyboard_key_bg_pressed.xml @@ -1,5 +1,5 @@ - + diff --git a/opencloudApp/src/main/res/drawable/numberkeyboard_key_text_color.xml b/opencloudApp/src/main/res/drawable/numberkeyboard_key_text_color.xml index e632fde92c..d7c97a311a 100644 --- a/opencloudApp/src/main/res/drawable/numberkeyboard_key_text_color.xml +++ b/opencloudApp/src/main/res/drawable/numberkeyboard_key_text_color.xml @@ -1,5 +1,5 @@ - - + + diff --git a/opencloudApp/src/main/res/drawable/top_progress_bar_determinate.xml b/opencloudApp/src/main/res/drawable/top_progress_bar_determinate.xml index 84f79db007..de9bc6237e 100644 --- a/opencloudApp/src/main/res/drawable/top_progress_bar_determinate.xml +++ b/opencloudApp/src/main/res/drawable/top_progress_bar_determinate.xml @@ -4,7 +4,7 @@ + android:drawable="?attr/colorSurface" /> @@ -78,7 +78,7 @@ android:id="@+id/account_quota_status_text" android:layout_width="0dp" android:layout_height="wrap_content" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/opencloudApp/src/main/res/layout-sw600dp/whats_new_activity.xml b/opencloudApp/src/main/res/layout-sw600dp/whats_new_activity.xml index c7591ef0da..fe665a4105 100644 --- a/opencloudApp/src/main/res/layout-sw600dp/whats_new_activity.xml +++ b/opencloudApp/src/main/res/layout-sw600dp/whats_new_activity.xml @@ -36,7 +36,7 @@ android:layout_gravity="center_vertical|center_horizontal" android:layout_weight="1" android:text="@string/welcome_feature_skip_button" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="14sp" /> + app:tint="?attr/colorOnSurface" /> + app:tint="?attr/colorOnSurface" /> + app:tint="?attr/colorOnSurface" /> + app:tint="?attr/colorOnSurface" /> @@ -156,7 +156,7 @@ android:text="@string/used_quota_title_manage_accounts" android:layout_marginEnd="@dimen/item_file_grid_margin" android:textSize="@dimen/two_line_secondary_text_size" - android:textColor="@color/textColor"/> + android:textColor="?attr/colorOnSurfaceVariant"/> diff --git a/opencloudApp/src/main/res/layout/activity_pattern_lock.xml b/opencloudApp/src/main/res/layout/activity_pattern_lock.xml index ba99a5fc9f..94d4bab0ba 100644 --- a/opencloudApp/src/main/res/layout/activity_pattern_lock.xml +++ b/opencloudApp/src/main/res/layout/activity_pattern_lock.xml @@ -32,7 +32,7 @@ @@ -71,7 +71,7 @@ android:layout_marginTop="@dimen/standard_half_padding" android:padding="@dimen/standard_padding" android:text="@string/global_name" - android:textColor="@color/black" + android:textColor="?attr/colorOnSurface" android:gravity="bottom" android:textSize="15sp" /> @@ -102,7 +102,7 @@ android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:text="@string/create_shortcut_dialog_url_extension" - android:textColor="@color/black" + android:textColor="?attr/colorOnSurface" android:textSize="15sp" /> @@ -127,7 +127,7 @@ @@ -38,7 +38,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginVertical="@dimen/activity_vertical_margin" - android:textColor="@color/black" + android:textColor="?attr/colorOnSurface" tools:text="@tools:sample/lorem[8]" /> + android:textColor="?attr/colorOnSurface" /> + android:textColor="?attr/colorOnSurface" /> diff --git a/opencloudApp/src/main/res/layout/file_details_empty.xml b/opencloudApp/src/main/res/layout/file_details_empty.xml index 46bd088636..ae55a6cedc 100644 --- a/opencloudApp/src/main/res/layout/file_details_empty.xml +++ b/opencloudApp/src/main/res/layout/file_details_empty.xml @@ -20,7 +20,7 @@ android:id="@+id/fileDetailsEmptyLayout" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/background_color" + android:background="?android:attr/colorBackground" android:orientation="vertical" android:filterTouchesWhenObscured="true"> diff --git a/opencloudApp/src/main/res/layout/file_details_fragment.xml b/opencloudApp/src/main/res/layout/file_details_fragment.xml index ca656fb80a..58aaf2e9f6 100644 --- a/opencloudApp/src/main/res/layout/file_details_fragment.xml +++ b/opencloudApp/src/main/res/layout/file_details_fragment.xml @@ -28,14 +28,14 @@ android:layout_height="match_parent" android:layout_margin="5dp" android:elevation="10dp" - app:cardBackgroundColor="@color/background_color" + app:cardBackgroundColor="?attr/colorSurface" app:cardCornerRadius="8dp"> @@ -173,7 +173,7 @@ android:id="@+id/divider2" android:layout_width="match_parent" android:layout_height="wrap_content" - app:dividerColor="@color/list_divider_background" + app:dividerColor="?attr/colorOutline" app:layout_constraintBottom_toTopOf="@id/fdSize" app:layout_constraintStart_toStartOf="@id/fdModified" app:layout_constraintTop_toBottomOf="@id/fdModified" /> @@ -266,7 +266,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/activity_vertical_margin" - app:dividerColor="@color/list_divider_background" + app:dividerColor="?attr/colorOutline" app:layout_constraintStart_toStartOf="@id/fdLastSync" app:layout_constraintTop_toBottomOf="@id/fdLastSync" /> diff --git a/opencloudApp/src/main/res/layout/file_options_bottom_sheet_fragment.xml b/opencloudApp/src/main/res/layout/file_options_bottom_sheet_fragment.xml index 9c05116af0..ff292527f8 100644 --- a/opencloudApp/src/main/res/layout/file_options_bottom_sheet_fragment.xml +++ b/opencloudApp/src/main/res/layout/file_options_bottom_sheet_fragment.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@color/white" + android:background="?attr/colorSurface" android:padding="@dimen/standard_padding"> @@ -55,7 +55,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/standard_quarter_margin" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="@dimen/two_line_secondary_text_size" app:layout_constraintEnd_toEndOf="@+id/file_name_bottom_sheet" app:layout_constraintStart_toEndOf="@+id/file_separator_bottom_sheet" @@ -80,7 +80,7 @@ android:layout_width="0dp" android:layout_height="@dimen/bottom_sheet_fragment_divider_height" android:layout_marginTop="@dimen/standard_margin" - android:background="@color/bottom_sheet_fragment_item_color" + android:background="?attr/colorOutline" app:layout_constraintBottom_toTopOf="@id/scroll_bottom_sheet" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/opencloudApp/src/main/res/layout/fragment_migration_choice.xml b/opencloudApp/src/main/res/layout/fragment_migration_choice.xml index 16520abe06..1601202906 100644 --- a/opencloudApp/src/main/res/layout/fragment_migration_choice.xml +++ b/opencloudApp/src/main/res/layout/fragment_migration_choice.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/login_background_color" + android:background="?attr/colorPrimary" tools:context=".presentation.migration.MigrationIntroFragment"> @@ -64,6 +65,7 @@ android:layout_width="15dp" android:layout_height="15dp" android:src="@drawable/ic_shared_by_link" + android:tint="?attr/colorOnSurfaceVariant" android:visibility="gone" tools:visibility="visible" /> @@ -99,7 +101,7 @@ android:ellipsize="middle" android:gravity="center_horizontal" android:singleLine="true" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurface" android:textSize="16dip" tools:text="TextView" /> diff --git a/opencloudApp/src/main/res/layout/item_empty_dataset.xml b/opencloudApp/src/main/res/layout/item_empty_dataset.xml index 6204f63d7c..e86ddbc3c5 100644 --- a/opencloudApp/src/main/res/layout/item_empty_dataset.xml +++ b/opencloudApp/src/main/res/layout/item_empty_dataset.xml @@ -16,7 +16,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed" - app:tint="@color/grey" + app:tint="?attr/colorOnSurfaceVariant" tools:src="@drawable/ic_folder" /> @@ -102,7 +103,7 @@ android:id="@+id/file_list_size" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="@dimen/two_line_secondary_text_size" app:layout_constraintStart_toEndOf="@+id/share_icons_layout" app:layout_constraintTop_toBottomOf="@+id/Filename" @@ -114,7 +115,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="," - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="@dimen/two_line_secondary_text_size" app:layout_constraintStart_toEndOf="@+id/file_list_size" app:layout_constraintTop_toBottomOf="@+id/Filename" /> @@ -124,7 +125,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/standard_quarter_margin" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="@dimen/two_line_secondary_text_size" app:layout_constraintStart_toEndOf="@+id/file_list_separator" app:layout_constraintTop_toBottomOf="@id/Filename" diff --git a/opencloudApp/src/main/res/layout/list_footer.xml b/opencloudApp/src/main/res/layout/list_footer.xml index d5a9a86926..ffa963eb2f 100644 --- a/opencloudApp/src/main/res/layout/list_footer.xml +++ b/opencloudApp/src/main/res/layout/list_footer.xml @@ -15,7 +15,7 @@ android:padding="@dimen/standard_padding" android:layout_gravity="center" android:gravity="center" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:layout_marginBottom="56dp" /> diff --git a/opencloudApp/src/main/res/layout/log_list_item.xml b/opencloudApp/src/main/res/layout/log_list_item.xml index 6fa92026b5..d59ee81c27 100644 --- a/opencloudApp/src/main/res/layout/log_list_item.xml +++ b/opencloudApp/src/main/res/layout/log_list_item.xml @@ -66,7 +66,7 @@ android:layout_height="wrap_content" android:ellipsize="middle" android:singleLine="true" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurface" android:textSize="@dimen/two_line_primary_text_size" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -77,7 +77,7 @@ android:id="@+id/textView_subtitle_activity_logs_list" android:layout_width="0dp" android:layout_height="wrap_content" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="@dimen/two_line_secondary_text_size" app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="@id/textView_title_activity_logs_list" diff --git a/opencloudApp/src/main/res/layout/main_file_list_fragment.xml b/opencloudApp/src/main/res/layout/main_file_list_fragment.xml index de6c1c3603..5e2e71bf77 100644 --- a/opencloudApp/src/main/res/layout/main_file_list_fragment.xml +++ b/opencloudApp/src/main/res/layout/main_file_list_fragment.xml @@ -83,14 +83,14 @@ android:layout_marginTop="@dimen/standard_quarter_margin" android:text="@string/fab_refresh_text" android:textAllCaps="false" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:theme="@style/Theme.MaterialComponents.Bridge" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:icon="@drawable/ic_action_refresh" - app:iconTint="@color/white" + app:iconTint="?attr/colorOnPrimary" app:backgroundTint="@color/primary_button_background_color"/> diff --git a/opencloudApp/src/main/res/layout/manage_accounts_dialog.xml b/opencloudApp/src/main/res/layout/manage_accounts_dialog.xml index 84264206b5..88e47ee384 100644 --- a/opencloudApp/src/main/res/layout/manage_accounts_dialog.xml +++ b/opencloudApp/src/main/res/layout/manage_accounts_dialog.xml @@ -33,7 +33,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_horizontal_margin" - app:cardBackgroundColor="@color/background_color" + app:cardBackgroundColor="?attr/colorSurface" app:cardCornerRadius="@dimen/standard_margin" app:cardElevation="0dp" app:cardUseCompatPadding="true"> @@ -59,7 +59,7 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:tint="@color/white" /> + app:tint="?attr/colorOnPrimary" /> diff --git a/opencloudApp/src/main/res/layout/nav_drawer_footer.xml b/opencloudApp/src/main/res/layout/nav_drawer_footer.xml index 43a158ae50..6deb025c63 100644 --- a/opencloudApp/src/main/res/layout/nav_drawer_footer.xml +++ b/opencloudApp/src/main/res/layout/nav_drawer_footer.xml @@ -52,7 +52,7 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/standard_half_margin" android:singleLine="true" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurface" android:textSize="16sp" android:textStyle="bold" android:ellipsize="end" @@ -81,7 +81,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:text="@string/drawer_loading_quota" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/account_quota_bar" /> @@ -90,7 +90,7 @@ android:id="@+id/account_quota_status_text" android:layout_width="0dp" android:layout_height="wrap_content" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/opencloudApp/src/main/res/layout/nav_drawer_header.xml b/opencloudApp/src/main/res/layout/nav_drawer_header.xml index bb84e64cd1..cd98023fbb 100644 --- a/opencloudApp/src/main/res/layout/nav_drawer_header.xml +++ b/opencloudApp/src/main/res/layout/nav_drawer_header.xml @@ -53,7 +53,7 @@ android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" - android:textColor="@android:color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="14sp" android:textStyle="bold" app:layout_constraintBottom_toTopOf="@id/drawer_username_full" @@ -67,7 +67,7 @@ android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" - android:textColor="@android:color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="12sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@id/drawer_username" diff --git a/opencloudApp/src/main/res/layout/nav_main_container.xml b/opencloudApp/src/main/res/layout/nav_main_container.xml index 55788fa809..99dc1c1101 100644 --- a/opencloudApp/src/main/res/layout/nav_main_container.xml +++ b/opencloudApp/src/main/res/layout/nav_main_container.xml @@ -19,7 +19,7 @@ android:id="@+id/list_layout" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/background_color" > + android:background="?android:attr/colorBackground" > diff --git a/opencloudApp/src/main/res/layout/opencloud_toolbar.xml b/opencloudApp/src/main/res/layout/opencloud_toolbar.xml index e0b09b443a..92e32093be 100644 --- a/opencloudApp/src/main/res/layout/opencloud_toolbar.xml +++ b/opencloudApp/src/main/res/layout/opencloud_toolbar.xml @@ -62,11 +62,11 @@ android:gravity="center_vertical" android:maxLines="1" android:paddingHorizontal="@dimen/standard_half_padding" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="@dimen/toolbar_title_text_size" android:contentDescription="@string/content_description_search" app:drawableEndCompat="@drawable/ic_search" - app:drawableTint="@color/white" + app:drawableTint="?attr/colorOnPrimary" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/root_toolbar_avatar" app:layout_constraintStart_toEndOf="@id/root_toolbar_left_icon" diff --git a/opencloudApp/src/main/res/layout/passcodelock.xml b/opencloudApp/src/main/res/layout/passcodelock.xml index 85328fad0f..8f5f3c7d71 100644 --- a/opencloudApp/src/main/res/layout/passcodelock.xml +++ b/opencloudApp/src/main/res/layout/passcodelock.xml @@ -37,7 +37,7 @@ @@ -47,7 +47,7 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:textSize="16sp" - android:textColor="@color/color_accent" + android:textColor="?attr/colorOnSurface" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="16dp" @@ -67,7 +67,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:background="@color/color_accent" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="12sp" android:text="@string/button_no_thanks_name" /> @@ -79,7 +79,7 @@ android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:background="@color/color_accent" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="12sp" android:text="@string/button_later_name" /> @@ -89,7 +89,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:background="@color/color_accent" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="12sp" android:text="@string/button_rate_now_name" /> diff --git a/opencloudApp/src/main/res/layout/remove_files_dialog.xml b/opencloudApp/src/main/res/layout/remove_files_dialog.xml index 2eda3dadfb..c462bc525c 100644 --- a/opencloudApp/src/main/res/layout/remove_files_dialog.xml +++ b/opencloudApp/src/main/res/layout/remove_files_dialog.xml @@ -11,7 +11,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_horizontal_margin" - app:cardBackgroundColor="@color/background_color" + app:cardBackgroundColor="?attr/colorSurface" app:cardCornerRadius="@dimen/standard_half_margin" app:cardElevation="0dp"> @@ -41,7 +41,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" - android:textColor="@color/black" + android:textColor="?attr/colorOnSurface" android:textSize="@dimen/two_line_primary_text_size" android:layout_marginStart="@dimen/standard_margin" android:layout_marginEnd="@dimen/standard_margin" diff --git a/opencloudApp/src/main/res/layout/share_file_layout.xml b/opencloudApp/src/main/res/layout/share_file_layout.xml index 0cf292f7eb..1a495629b9 100644 --- a/opencloudApp/src/main/res/layout/share_file_layout.xml +++ b/opencloudApp/src/main/res/layout/share_file_layout.xml @@ -51,7 +51,7 @@ android:ellipsize="middle" android:singleLine="true" android:text="@string/placeholder_filename" - android:textColor="@color/black" + android:textColor="?attr/colorOnSurface" android:textSize="16sp" /> @@ -159,7 +159,7 @@ android:paddingStart="@dimen/standard_half_padding" android:text="@string/share_via_link_section_title" android:textAllCaps="true" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:textStyle="bold" android:accessibilityHeading="true"/> diff --git a/opencloudApp/src/main/res/layout/share_public_dialog.xml b/opencloudApp/src/main/res/layout/share_public_dialog.xml index 084e702add..1c42f81ea9 100644 --- a/opencloudApp/src/main/res/layout/share_public_dialog.xml +++ b/opencloudApp/src/main/res/layout/share_public_dialog.xml @@ -36,7 +36,7 @@ android:layout_height="wrap_content" android:padding="@dimen/standard_half_padding" android:text="@string/share_via_link_name_label" - android:textColor="@color/black" + android:textColor="?attr/colorOnSurface" android:textSize="15sp" /> @@ -137,7 +137,7 @@ android:layout_height="wrap_content" android:text="@string/share_via_link_copy_password_button" android:backgroundTint="@color/transparent" - android:textColor="@color/grey" + android:textColor="?attr/colorOnSurfaceVariant" android:enabled="false" style="?android:attr/borderlessButtonStyle" /> @@ -292,7 +292,7 @@ android:paddingRight="@dimen/standard_half_padding" android:paddingTop="@dimen/standard_half_padding" android:text="@string/share_via_link_expiration_date_label" - android:textColor="@color/black" + android:textColor="?attr/colorOnSurface" android:textSize="15sp" android:focusable="false"/> @@ -307,7 +307,7 @@ android:paddingLeft="@dimen/standard_half_padding" android:paddingRight="@dimen/standard_half_padding" android:textSize="12sp" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:visibility="gone" android:focusable="false"/> @@ -321,7 +321,7 @@ android:paddingRight="@dimen/standard_half_padding" android:paddingTop="@dimen/standard_half_padding" android:text="@string/share_via_link_expiration_date_label" - android:textColor="@color/half_black" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="15sp" android:visibility="gone" /> @@ -343,7 +343,7 @@ android:gravity="center_vertical" android:paddingLeft="@dimen/standard_half_padding" android:paddingRight="@dimen/standard_half_padding" - android:textColor="@color/secondaryTextColor" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="13sp" android:visibility="gone" /> diff --git a/opencloudApp/src/main/res/layout/share_public_link_item.xml b/opencloudApp/src/main/res/layout/share_public_link_item.xml index 179cad1a82..aeb97d613f 100644 --- a/opencloudApp/src/main/res/layout/share_public_link_item.xml +++ b/opencloudApp/src/main/res/layout/share_public_link_item.xml @@ -37,7 +37,7 @@ android:ellipsize="middle" android:singleLine="true" android:text="@string/username" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurface" android:textSize="@dimen/two_line_primary_text_size" /> diff --git a/opencloudApp/src/main/res/layout/sort_bottom_sheet_fragment.xml b/opencloudApp/src/main/res/layout/sort_bottom_sheet_fragment.xml index bf7d407785..fb7850bbd0 100644 --- a/opencloudApp/src/main/res/layout/sort_bottom_sheet_fragment.xml +++ b/opencloudApp/src/main/res/layout/sort_bottom_sheet_fragment.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@color/white" + android:background="?attr/colorSurface" android:padding="@dimen/standard_padding"> diff --git a/opencloudApp/src/main/res/layout/sort_options_layout.xml b/opencloudApp/src/main/res/layout/sort_options_layout.xml index 35d66edea3..0c71863f62 100644 --- a/opencloudApp/src/main/res/layout/sort_options_layout.xml +++ b/opencloudApp/src/main/res/layout/sort_options_layout.xml @@ -24,7 +24,7 @@ android:id="@+id/sort_type_title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/white" + android:textColor="?attr/colorOnPrimary" android:textSize="@dimen/two_line_primary_text_size" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/sort_type_icon" @@ -36,7 +36,7 @@ android:id="@+id/sort_type_icon" android:layout_width="@dimen/bottom_sheet_fragment_item_icon_size" android:layout_height="@dimen/bottom_sheet_fragment_arrow_icon_size" - android:tint="@color/white" + android:tint="?attr/colorOnPrimary" app:layout_constraintBottom_toBottomOf="@+id/sort_type_title" app:layout_constraintStart_toEndOf="@+id/sort_type_title" app:layout_constraintTop_toTopOf="@+id/sort_type_title" @@ -49,7 +49,7 @@ android:layout_height="wrap_content" android:padding="@dimen/standard_half_padding" android:src="@drawable/ic_baseline_view_list" - android:tint="@color/white" + android:tint="?attr/colorOnPrimary" android:contentDescription="@string/content_description_type_view" app:layout_constraintBottom_toBottomOf="@id/sort_type_selector" app:layout_constraintEnd_toEndOf="parent" diff --git a/opencloudApp/src/main/res/layout/space_header.xml b/opencloudApp/src/main/res/layout/space_header.xml index 0e2784f49c..7206694ee5 100644 --- a/opencloudApp/src/main/res/layout/space_header.xml +++ b/opencloudApp/src/main/res/layout/space_header.xml @@ -25,14 +25,14 @@ android:layout_height="wrap_content" android:paddingHorizontal="@dimen/standard_padding" android:paddingVertical="@dimen/standard_half_padding" - android:background="@color/spaces_card_background_color"> + android:background="?attr/colorSurface"> @@ -59,7 +59,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/standard_half_margin" android:singleLine="true" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurface" android:textSize="18sp" android:textStyle="bold" tools:text="Name" /> @@ -71,7 +71,7 @@ android:layout_marginHorizontal="@dimen/standard_half_margin" android:layout_marginBottom="@dimen/standard_half_margin" android:singleLine="true" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurfaceVariant" android:textSize="15sp" tools:text="Subtitle" /> diff --git a/opencloudApp/src/main/res/layout/ssl_untrusted_cert_layout.xml b/opencloudApp/src/main/res/layout/ssl_untrusted_cert_layout.xml index 67b75a831f..c129f9528e 100644 --- a/opencloudApp/src/main/res/layout/ssl_untrusted_cert_layout.xml +++ b/opencloudApp/src/main/res/layout/ssl_untrusted_cert_layout.xml @@ -33,7 +33,7 @@ android:paddingBottom="@dimen/standard_padding" android:text="@string/ssl_validator_header" android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="@android:color/black" + android:textColor="?attr/colorOnSurface" /> diff --git a/opencloudApp/src/main/res/layout/upload_list_item.xml b/opencloudApp/src/main/res/layout/upload_list_item.xml index ae2348c0bb..4567673c0a 100755 --- a/opencloudApp/src/main/res/layout/upload_list_item.xml +++ b/opencloudApp/src/main/res/layout/upload_list_item.xml @@ -41,7 +41,7 @@ android:layout_gravity="center_vertical" android:ellipsize="middle" android:singleLine="true" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurface" tools:text="@string/placeholder_filename" android:textSize="16sp" /> @@ -54,7 +54,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="start" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:ellipsize="middle" android:singleLine="true" tools:text="@string/placeholder_filesize" @@ -64,7 +64,7 @@ android:id="@+id/upload_date" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" tools:text="@string/placeholder_timestamp" android:textSize="12sp" /> @@ -72,7 +72,7 @@ android:id="@+id/upload_status" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" tools:text="@string/uploads_view_upload_status_succeeded" android:textSize="12sp" /> @@ -89,7 +89,7 @@ android:id="@+id/upload_account" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/list_item_lastmod_and_filesize_text" + android:textColor="?attr/colorOnSurfaceVariant" android:singleLine="true" tools:text="@string/auth_username" android:textSize="12sp" /> diff --git a/opencloudApp/src/main/res/layout/uploader_layout.xml b/opencloudApp/src/main/res/layout/uploader_layout.xml index 8c81f8ca42..96947d1a8a 100644 --- a/opencloudApp/src/main/res/layout/uploader_layout.xml +++ b/opencloudApp/src/main/res/layout/uploader_layout.xml @@ -65,7 +65,7 @@ android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" - android:divider="@color/list_divider_background" + android:divider="?attr/colorOutline" android:dividerHeight="1dip" android:visibility="gone" tools:listitem="@layout/uploader_list_item_layout" /> diff --git a/opencloudApp/src/main/res/layout/uploader_list_item_layout.xml b/opencloudApp/src/main/res/layout/uploader_list_item_layout.xml index 8998d0828a..e3eeeb4f9c 100644 --- a/opencloudApp/src/main/res/layout/uploader_list_item_layout.xml +++ b/opencloudApp/src/main/res/layout/uploader_list_item_layout.xml @@ -49,7 +49,7 @@ android:layout_marginEnd="4dp" android:ellipsize="middle" android:singleLine="true" - android:textColor="@color/textColor" + android:textColor="?attr/colorOnSurface" android:textSize="16dip" /> diff --git a/opencloudApp/src/main/res/layout/whats_new_activity.xml b/opencloudApp/src/main/res/layout/whats_new_activity.xml index 56cf720573..3dd1b25ccb 100644 --- a/opencloudApp/src/main/res/layout/whats_new_activity.xml +++ b/opencloudApp/src/main/res/layout/whats_new_activity.xml @@ -37,7 +37,7 @@ android:layout_gravity="center_vertical|center_horizontal" android:layout_weight="1" android:text="@string/welcome_feature_skip_button" - android:textColor="@color/white" /> + android:textColor="?attr/colorOnPrimary" /> @@ -32,5 +32,5 @@ android:layout_margin="@dimen/standard_margin" android:layout_gravity="center_horizontal" android:gravity="center_horizontal" - android:textColor="@color/white" /> + android:textColor="?attr/colorOnPrimary" /> \ No newline at end of file diff --git a/opencloudApp/src/main/res/values-night/colors.xml b/opencloudApp/src/main/res/values-night/colors.xml new file mode 100644 index 0000000000..37d5563faf --- /dev/null +++ b/opencloudApp/src/main/res/values-night/colors.xml @@ -0,0 +1,14 @@ + + + + + #121212 + #1E1E1E + #FFFFFF + #E0E0E0 + #A5ABAF + #FFFFFF + #9AD6E6 + #31515D + @color/theme_color_surface + diff --git a/opencloudApp/src/main/res/values/attrs.xml b/opencloudApp/src/main/res/values/attrs.xml index 8d571eb0c3..f46bfb558b 100644 --- a/opencloudApp/src/main/res/values/attrs.xml +++ b/opencloudApp/src/main/res/values/attrs.xml @@ -1,6 +1,8 @@ + + diff --git a/opencloudApp/src/main/res/values/colors.xml b/opencloudApp/src/main/res/values/colors.xml index 02e687b6dc..b024f60a98 100644 --- a/opencloudApp/src/main/res/values/colors.xml +++ b/opencloudApp/src/main/res/values/colors.xml @@ -24,12 +24,21 @@ #19353F @color/opencloud_petrol_accent + + #FFFFFF + #FFFFFF + #000000 + #525757 + #707575 + #FFFFFF + @color/primary + #D6E6EC + #21434F #396676 #00ddff #525757 - #707575 #BDBDBD #000000 #FFFFFF @@ -38,7 +47,6 @@ #f1f1f1 #808080 #B2000000 - @color/black #000000 #eee #DDDDDD diff --git a/opencloudApp/src/main/res/values/setup.xml b/opencloudApp/src/main/res/values/setup.xml index 1b0b7dfdcd..5bf065aa31 100644 --- a/opencloudApp/src/main/res/values/setup.xml +++ b/opencloudApp/src/main/res/values/setup.xml @@ -38,7 +38,6 @@ @color/white @color/white @color/color_accent - #FFFFFF @color/primary @color/color_accent @color/white diff --git a/opencloudApp/src/main/res/values/strings.xml b/opencloudApp/src/main/res/values/strings.xml index 0a4de8366d..a28f5cf4d8 100644 --- a/opencloudApp/src/main/res/values/strings.xml +++ b/opencloudApp/src/main/res/values/strings.xml @@ -39,6 +39,10 @@ GitHub Discussions Help General + Appearance + System default + Light + Dark Logging More Security diff --git a/opencloudApp/src/main/res/values/styles.xml b/opencloudApp/src/main/res/values/styles.xml index cdf9a08a29..dc4f0cc864 100644 --- a/opencloudApp/src/main/res/values/styles.xml +++ b/opencloudApp/src/main/res/values/styles.xml @@ -25,8 +25,8 @@ - @@ -182,6 +190,7 @@ diff --git a/opencloudApp/src/main/res/xml/settings.xml b/opencloudApp/src/main/res/xml/settings.xml index 46749074b0..c0806bfeb8 100644 --- a/opencloudApp/src/main/res/xml/settings.xml +++ b/opencloudApp/src/main/res/xml/settings.xml @@ -18,7 +18,15 @@ + + . + */ + +package eu.opencloud.android.presentation.settings + +import androidx.appcompat.app.AppCompatDelegate +import org.junit.Assert.assertEquals +import org.junit.Test + +class AppearanceModeTest { + + @Test + fun `maps persisted appearance values to night modes`() { + assertEquals(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, AppearanceMode.fromPreferenceValue("SYSTEM").nightMode) + assertEquals(AppCompatDelegate.MODE_NIGHT_NO, AppearanceMode.fromPreferenceValue("LIGHT").nightMode) + assertEquals(AppCompatDelegate.MODE_NIGHT_YES, AppearanceMode.fromPreferenceValue("DARK").nightMode) + } + + @Test + fun `uses system mode for missing or invalid persisted appearance values`() { + assertEquals(AppearanceMode.SYSTEM, AppearanceMode.fromPreferenceValue(null)) + assertEquals(AppearanceMode.SYSTEM, AppearanceMode.fromPreferenceValue("INVALID")) + } + + @Test + fun `uses the mode name as its canonical persisted value`() { + assertEquals("SYSTEM", AppearanceMode.fromPreferenceValue(null).name) + assertEquals("SYSTEM", AppearanceMode.fromPreferenceValue("INVALID").name) + assertEquals("LIGHT", AppearanceMode.fromPreferenceValue("LIGHT").name) + assertEquals("DARK", AppearanceMode.fromPreferenceValue("DARK").name) + } +}