mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-08 19:44:09 +08:00
Added: Add support for shared day/night theming across termux apps
With this commit, activities will automatically change theme between day/night if `night-mode` `termux.properties` is not set or is set to `system` without requiring app restart. Dialog theming will be fully added in a later commit and may currently be in an inconsistent state or have crashes. The `uiMode` has been removed from `configChanges` of `TermuxActivity`, this may cause termux app to restart if samsung DEX mode is changed, if it does, then users should report it so that it can be fixed by re-adding the value and ignoring the change inside `TermuxActivity.onConfigurationChanged()`. The docs don't state if its necessary. Check related pull request #1446. Running `termux-reload-settings` will also restart `TermuxActivity`, the activity data should be preserved.
This commit is contained in:
@@ -17,6 +17,7 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.termux.shared.R;
|
||||
import com.termux.shared.activity.media.AppCompatActivityUtils;
|
||||
import com.termux.shared.data.DataUtils;
|
||||
import com.termux.shared.file.FileUtils;
|
||||
import com.termux.shared.file.filesystem.FileType;
|
||||
@@ -26,6 +27,7 @@ import com.termux.shared.termux.TermuxConstants;
|
||||
import com.termux.shared.markdown.MarkdownUtils;
|
||||
import com.termux.shared.interact.ShareUtils;
|
||||
import com.termux.shared.models.ReportInfo;
|
||||
import com.termux.shared.theme.NightMode;
|
||||
|
||||
import org.commonmark.node.FencedCodeBlock;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -72,6 +74,8 @@ public class ReportActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
Logger.logVerbose(LOG_TAG, "onCreate");
|
||||
|
||||
AppCompatActivityUtils.setNightMode(this, NightMode.getAppNightMode().getName(), true);
|
||||
|
||||
setContentView(R.layout.activity_report);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
|
@@ -0,0 +1,120 @@
|
||||
package com.termux.shared.activity.media;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.termux.shared.logger.Logger;
|
||||
import com.termux.shared.theme.NightMode;
|
||||
|
||||
public class AppCompatActivityUtils {
|
||||
|
||||
private static final String LOG_TAG = "AppCompatActivityUtils";
|
||||
|
||||
|
||||
/** Set activity night mode.
|
||||
*
|
||||
* @param activity The host {@link AppCompatActivity}.
|
||||
* @param name The {@link String} representing the name for a {@link NightMode}.
|
||||
* @param local If set to {@code true}, then a call to {@link AppCompatDelegate#setLocalNightMode(int)}
|
||||
* will be made, otherwise to {@link AppCompatDelegate#setDefaultNightMode(int)}.
|
||||
*/
|
||||
public static void setNightMode(AppCompatActivity activity, String name, boolean local) {
|
||||
if (name == null) return;
|
||||
NightMode nightMode = NightMode.modeOf(name);
|
||||
if (nightMode != null) {
|
||||
if (local) {
|
||||
if (activity != null) {
|
||||
activity.getDelegate().setLocalNightMode(nightMode.getMode());
|
||||
}
|
||||
} else {
|
||||
AppCompatDelegate.setDefaultNightMode(nightMode.getMode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Set activity toolbar.
|
||||
*
|
||||
* @param activity The host {@link AppCompatActivity}.
|
||||
* @param id The toolbar resource id.
|
||||
*/
|
||||
public static void setToolbar(@NonNull AppCompatActivity activity, @IdRes int id) {
|
||||
Toolbar toolbar = activity.findViewById(id);
|
||||
if (toolbar != null)
|
||||
activity.setSupportActionBar(toolbar);
|
||||
}
|
||||
|
||||
/** Set activity toolbar title.
|
||||
*
|
||||
* @param activity The host {@link AppCompatActivity}.
|
||||
* @param id The toolbar resource id.
|
||||
* @param title The toolbar title {@link String}.
|
||||
* @param titleAppearance The toolbar title TextAppearance resource id.
|
||||
*/
|
||||
public static void setToolbarTitle(@NonNull AppCompatActivity activity, @IdRes int id,
|
||||
String title, @StyleRes int titleAppearance) {
|
||||
Toolbar toolbar = activity.findViewById(id);
|
||||
if (toolbar != null) {
|
||||
//toolbar.setTitle(title); // Does not work
|
||||
final ActionBar actionBar = activity.getSupportActionBar();
|
||||
if (actionBar != null)
|
||||
actionBar.setTitle(title);
|
||||
|
||||
try {
|
||||
if (titleAppearance != 0)
|
||||
toolbar.setTitleTextAppearance(activity, titleAppearance);
|
||||
} catch (Exception e) {
|
||||
Logger.logStackTraceWithMessage(LOG_TAG, "Failed to set toolbar title appearance to style resource id " + titleAppearance, e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** Set activity toolbar subtitle.
|
||||
*
|
||||
* @param activity The host {@link AppCompatActivity}.
|
||||
* @param id The toolbar resource id.
|
||||
* @param subtitle The toolbar subtitle {@link String}.
|
||||
* @param subtitleAppearance The toolbar subtitle TextAppearance resource id.
|
||||
*/
|
||||
public static void setToolbarSubtitle(@NonNull AppCompatActivity activity, @IdRes int id,
|
||||
String subtitle, @StyleRes int subtitleAppearance) {
|
||||
Toolbar toolbar = activity.findViewById(id);
|
||||
if (toolbar != null) {
|
||||
toolbar.setSubtitle(subtitle);
|
||||
try {
|
||||
if (subtitleAppearance != 0)
|
||||
toolbar.setSubtitleTextAppearance(activity, subtitleAppearance);
|
||||
} catch (Exception e) {
|
||||
Logger.logStackTraceWithMessage(LOG_TAG, "Failed to set toolbar subtitle appearance to style resource id " + subtitleAppearance, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Set whether back button should be shown in activity toolbar.
|
||||
*
|
||||
* @param activity The host {@link AppCompatActivity}.
|
||||
* @param showBackButtonInActionBar Set to {@code true} to enable and {@code false} to disable.
|
||||
*/
|
||||
public static void setShowBackButtonInActionBar(@NonNull AppCompatActivity activity,
|
||||
boolean showBackButtonInActionBar) {
|
||||
final ActionBar actionBar = activity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
if (showBackButtonInActionBar) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
} else {
|
||||
actionBar.setDisplayHomeAsUpEnabled(false);
|
||||
actionBar.setDisplayShowHomeEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -17,6 +17,7 @@ import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.termux.shared.R;
|
||||
import com.termux.shared.theme.ThemeUtils;
|
||||
|
||||
import org.commonmark.ext.gfm.strikethrough.Strikethrough;
|
||||
import org.commonmark.node.BlockQuote;
|
||||
@@ -152,11 +153,14 @@ public class MarkdownUtils {
|
||||
|
||||
@Override
|
||||
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {
|
||||
builder
|
||||
// set color for inline code
|
||||
.setFactory(Code.class, (configuration, props) -> new Object[]{
|
||||
new BackgroundColorSpan(ContextCompat.getColor(context, R.color.background_markdown_code_inline)),
|
||||
});
|
||||
// Do not change color for night themes
|
||||
if (!ThemeUtils.isNightModeEnabled(context)) {
|
||||
builder
|
||||
// set color for inline code
|
||||
.setFactory(Code.class, (configuration, props) -> new Object[]{
|
||||
new BackgroundColorSpan(ContextCompat.getColor(context, R.color.background_markdown_code_inline)),
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.build();
|
||||
|
@@ -32,7 +32,9 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.termux.shared.R;
|
||||
import com.termux.shared.termux.terminal.io.TerminalExtraKeys;
|
||||
import com.termux.shared.theme.ThemeUtils;
|
||||
|
||||
/**
|
||||
* A {@link View} showing extra keys (such as Escape, Ctrl, Alt) not normally available on an Android soft
|
||||
@@ -107,16 +109,26 @@ public final class ExtraKeysView extends GridLayout {
|
||||
}
|
||||
|
||||
|
||||
/** Defines the default value for {@link #mButtonTextColor}. */
|
||||
/** Defines the default value for {@link #mButtonTextColor} defined by current theme. */
|
||||
public static final int ATTR_BUTTON_TEXT_COLOR = R.attr.extraKeysButtonTextColor;
|
||||
/** Defines the default value for {@link #mButtonActiveTextColor} defined by current theme. */
|
||||
public static final int ATTR_BUTTON_ACTIVE_TEXT_COLOR = R.attr.extraKeysButtonActiveTextColor;
|
||||
/** Defines the default value for {@link #mButtonBackgroundColor} defined by current theme. */
|
||||
public static final int ATTR_BUTTON_BACKGROUND_COLOR = R.attr.extraKeysButtonBackgroundColor;
|
||||
/** Defines the default value for {@link #mButtonActiveBackgroundColor} defined by current theme. */
|
||||
public static final int ATTR_BUTTON_ACTIVE_BACKGROUND_COLOR = R.attr.extraKeysButtonActiveBackgroundColor;
|
||||
|
||||
/** Defines the default fallback value for {@link #mButtonTextColor} if {@link #ATTR_BUTTON_TEXT_COLOR} is undefined. */
|
||||
public static final int DEFAULT_BUTTON_TEXT_COLOR = 0xFFFFFFFF;
|
||||
/** Defines the default value for {@link #mButtonActiveTextColor}. */
|
||||
/** Defines the default fallback value for {@link #mButtonActiveTextColor} if {@link #ATTR_BUTTON_ACTIVE_TEXT_COLOR} is undefined. */
|
||||
public static final int DEFAULT_BUTTON_ACTIVE_TEXT_COLOR = 0xFF80DEEA;
|
||||
/** Defines the default value for {@link #mButtonBackgroundColor}. */
|
||||
/** Defines the default fallback value for {@link #mButtonBackgroundColor} if {@link #ATTR_BUTTON_BACKGROUND_COLOR} is undefined. */
|
||||
public static final int DEFAULT_BUTTON_BACKGROUND_COLOR = 0x00000000;
|
||||
/** Defines the default value for {@link #mButtonActiveBackgroundColor}. */
|
||||
/** Defines the default fallback value for {@link #mButtonActiveBackgroundColor} if {@link #ATTR_BUTTON_ACTIVE_BACKGROUND_COLOR} is undefined. */
|
||||
public static final int DEFAULT_BUTTON_ACTIVE_BACKGROUND_COLOR = 0xFF7F7F7F;
|
||||
|
||||
|
||||
|
||||
/** Defines the minimum allowed duration in milliseconds for {@link #mLongPressTimeout}. */
|
||||
public static final int MIN_LONG_PRESS_DURATION = 200;
|
||||
/** Defines the maximum allowed duration in milliseconds for {@link #mLongPressTimeout}. */
|
||||
@@ -202,8 +214,13 @@ public final class ExtraKeysView extends GridLayout {
|
||||
|
||||
setRepetitiveKeys(ExtraKeysConstants.PRIMARY_REPETITIVE_KEYS);
|
||||
setSpecialButtons(getDefaultSpecialButtons(this));
|
||||
setButtonColors(DEFAULT_BUTTON_TEXT_COLOR, DEFAULT_BUTTON_ACTIVE_TEXT_COLOR,
|
||||
DEFAULT_BUTTON_BACKGROUND_COLOR, DEFAULT_BUTTON_ACTIVE_BACKGROUND_COLOR);
|
||||
|
||||
setButtonColors(
|
||||
ThemeUtils.getSystemAttrColor(context, ATTR_BUTTON_TEXT_COLOR, DEFAULT_BUTTON_TEXT_COLOR),
|
||||
ThemeUtils.getSystemAttrColor(context, ATTR_BUTTON_ACTIVE_TEXT_COLOR, DEFAULT_BUTTON_ACTIVE_TEXT_COLOR),
|
||||
ThemeUtils.getSystemAttrColor(context, ATTR_BUTTON_BACKGROUND_COLOR, DEFAULT_BUTTON_BACKGROUND_COLOR),
|
||||
ThemeUtils.getSystemAttrColor(context, ATTR_BUTTON_ACTIVE_BACKGROUND_COLOR, DEFAULT_BUTTON_ACTIVE_BACKGROUND_COLOR));
|
||||
|
||||
setLongPressTimeout(ViewConfiguration.getLongPressTimeout());
|
||||
setLongPressRepeatDelay(DEFAULT_LONG_PRESS_REPEAT_DELAY);
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ public enum NightMode {
|
||||
private static final String LOG_TAG = "NightMode";
|
||||
|
||||
private final String name;
|
||||
private final int mode;
|
||||
private final @AppCompatDelegate.NightMode int mode;
|
||||
|
||||
NightMode(final String name, int mode) {
|
||||
this.name = name;
|
||||
|
@@ -1,10 +1,19 @@
|
||||
package com.termux.shared.theme;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class ThemeUtils {
|
||||
|
||||
public static final int ATTR_TEXT_COLOR_PRIMARY = android.R.attr.textColorPrimary;
|
||||
public static final int ATTR_TEXT_COLOR_SECONDARY = android.R.attr.textColorSecondary;
|
||||
public static final int ATTR_TEXT_COLOR = android.R.attr.textColor;
|
||||
public static final int ATTR_TEXT_COLOR_LINK = android.R.attr.textColorLink;
|
||||
|
||||
/**
|
||||
* Will return true if system has enabled night mode.
|
||||
* https://developer.android.com/guide/topics/resources/providing-resources#NightQualifier
|
||||
@@ -28,4 +37,50 @@ public class ThemeUtils {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Get {@link #ATTR_TEXT_COLOR_PRIMARY} value being used by current theme. */
|
||||
public static int getTextColorPrimary(Context context) {
|
||||
return getSystemAttrColor(context, ATTR_TEXT_COLOR_PRIMARY);
|
||||
}
|
||||
|
||||
/** Get {@link #ATTR_TEXT_COLOR_SECONDARY} value being used by current theme. */
|
||||
public static int getTextColorSecondary(Context context) {
|
||||
return getSystemAttrColor(context, ATTR_TEXT_COLOR_SECONDARY);
|
||||
}
|
||||
|
||||
/** Get {@link #ATTR_TEXT_COLOR} value being used by current theme. */
|
||||
public static int getTextColor(Context context) {
|
||||
return getSystemAttrColor(context, ATTR_TEXT_COLOR);
|
||||
}
|
||||
|
||||
/** Get {@link #ATTR_TEXT_COLOR_LINK} value being used by current theme. */
|
||||
public static int getTextColorLink(Context context) {
|
||||
return getSystemAttrColor(context, ATTR_TEXT_COLOR_LINK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Wrapper for {@link #getSystemAttrColor(Context, int, int)} with {@code def} value {@code 0}. */
|
||||
public static int getSystemAttrColor(Context context, int attr) {
|
||||
return getSystemAttrColor(context, attr, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a values defined by the current heme listed in attrs.
|
||||
*
|
||||
* @param context The context for operations. It must be an instance of {@link Activity} or
|
||||
* {@link AppCompatActivity} or one with which a theme attribute can be got.
|
||||
* Do no use application context.
|
||||
* @param attr The attr id.
|
||||
* @param def The def value to return.
|
||||
* @return Returns the {@code attr} value if found, otherwise {@code def}.
|
||||
*/
|
||||
public static int getSystemAttrColor(Context context, int attr, int def) {
|
||||
TypedArray typedArray = context.getTheme().obtainStyledAttributes(new int[] { attr });
|
||||
int color = typedArray.getColor(0, def);
|
||||
typedArray.recycle();
|
||||
return color;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user