Skip to content

Commit 6631599

Browse files
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.
1 parent f3f434a commit 6631599

30 files changed

+584
-138
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ android {
1616
implementation "androidx.drawerlayout:drawerlayout:1.1.1"
1717
implementation "androidx.preference:preference:1.1.1"
1818
implementation "androidx.viewpager:viewpager:1.0.0"
19+
implementation "com.google.android.material:material:1.4.0"
1920
implementation "com.google.guava:guava:24.1-jre"
2021
implementation "io.noties.markwon:core:$markwonVersion"
2122
implementation "io.noties.markwon:ext-strikethrough:$markwonVersion"

app/src/main/AndroidManifest.xml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@
4646
android:requestLegacyExternalStorage="true"
4747
android:roundIcon="@mipmap/ic_launcher_round"
4848
android:supportsRtl="false"
49-
android:theme="@style/Theme.Termux">
49+
android:theme="@style/Theme.TermuxApp.DayNight.DarkActionBar">
5050

5151
<activity
5252
android:name=".app.TermuxActivity"
53-
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
53+
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
5454
android:label="@string/application_name"
5555
android:launchMode="singleTask"
56-
android:resizeableActivity="true">
56+
android:resizeableActivity="true"
57+
android:theme="@style/Theme.TermuxActivity.DayNight.NoActionBar">
5758
<intent-filter>
5859
<action android:name="android.intent.action.MAIN" />
5960

@@ -88,20 +89,18 @@
8889
android:exported="false"
8990
android:label="@string/application_name"
9091
android:parentActivityName=".app.TermuxActivity"
91-
android:resizeableActivity="true"
92-
android:theme="@android:style/Theme.Material.Light.DarkActionBar" />
92+
android:resizeableActivity="true" />
9393

9494
<activity
9595
android:name=".app.activities.SettingsActivity"
9696
android:exported="true"
9797
android:label="@string/title_activity_termux_settings"
98-
android:theme="@style/Theme.AppCompat.Light.DarkActionBar" />
98+
android:theme="@style/Theme.TermuxApp.DayNight.NoActionBar" />
9999

100100
<activity
101101
android:name=".shared.activities.ReportActivity"
102-
android:theme="@style/Theme.AppCompat.TermuxReportActivity"
103-
android:documentLaunchMode="intoExisting"
104-
/>
102+
android:theme="@style/Theme.MarkdownViewActivity.DayNight"
103+
android:documentLaunchMode="intoExisting" />
105104

106105
<activity
107106
android:name=".filepicker.TermuxFileReceiverActivity"

app/src/main/java/com/termux/app/TermuxActivity.java

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.termux.app;
22

33
import android.annotation.SuppressLint;
4-
import android.app.Activity;
54
import android.app.AlertDialog;
65
import android.content.ActivityNotFoundException;
76
import android.content.BroadcastReceiver;
@@ -10,7 +9,6 @@
109
import android.content.Intent;
1110
import android.content.IntentFilter;
1211
import android.content.ServiceConnection;
13-
import android.graphics.Color;
1412
import android.net.Uri;
1513
import android.os.Build;
1614
import android.os.Bundle;
@@ -34,6 +32,7 @@
3432
import com.termux.app.terminal.TermuxActivityRootView;
3533
import com.termux.shared.activities.ReportActivity;
3634
import com.termux.shared.activity.ActivityUtils;
35+
import com.termux.shared.activity.media.AppCompatActivityUtils;
3736
import com.termux.shared.data.IntentUtils;
3837
import com.termux.shared.android.PermissionUtils;
3938
import com.termux.shared.termux.TermuxConstants;
@@ -52,7 +51,6 @@
5251
import com.termux.shared.termux.TermuxUtils;
5352
import com.termux.shared.termux.theme.TermuxThemeUtils;
5453
import com.termux.shared.theme.NightMode;
55-
import com.termux.shared.theme.ThemeUtils;
5654
import com.termux.shared.view.ViewUtils;
5755
import com.termux.terminal.TerminalSession;
5856
import com.termux.terminal.TerminalSessionClient;
@@ -62,7 +60,7 @@
6260

6361
import androidx.annotation.NonNull;
6462
import androidx.annotation.Nullable;
65-
import androidx.core.content.ContextCompat;
63+
import androidx.appcompat.app.AppCompatActivity;
6664
import androidx.drawerlayout.widget.DrawerLayout;
6765
import androidx.viewpager.widget.ViewPager;
6866

@@ -78,7 +76,7 @@
7876
* </ul>
7977
* about memory leaks.
8078
*/
81-
public final class TermuxActivity extends Activity implements ServiceConnection {
79+
public final class TermuxActivity extends AppCompatActivity implements ServiceConnection {
8280

8381
/**
8482
* The connection to the {@link TermuxService}. Requested in {@link #onCreate(Bundle)} with a call to
@@ -228,8 +226,6 @@ public void onCreate(Bundle savedInstanceState) {
228226
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
229227
}
230228

231-
setDrawerTheme();
232-
233229
setTermuxTerminalViewAndClients();
234230

235231
setTerminalToolbarView(savedInstanceState);
@@ -340,6 +336,8 @@ public void onDestroy() {
340336

341337
@Override
342338
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
339+
Logger.logVerbose(LOG_TAG, "onSaveInstanceState");
340+
343341
super.onSaveInstanceState(savedInstanceState);
344342
saveTerminalToolbarTextInput(savedInstanceState);
345343
}
@@ -413,19 +411,10 @@ private void setActivityTheme() {
413411
// Update NightMode.APP_NIGHT_MODE
414412
TermuxThemeUtils.setAppNightMode(mProperties.getNightMode());
415413

416-
if (ThemeUtils.shouldEnableDarkTheme(this, NightMode.getAppNightMode().getName())) {
417-
this.setTheme(R.style.Theme_Termux_Black);
418-
} else {
419-
this.setTheme(R.style.Theme_Termux);
420-
}
421-
}
422-
423-
private void setDrawerTheme() {
424-
if (ThemeUtils.shouldEnableDarkTheme(this, NightMode.getAppNightMode().getName())) {
425-
findViewById(R.id.left_drawer).setBackgroundColor(ContextCompat.getColor(this,
426-
android.R.color.background_dark));
427-
((ImageButton) findViewById(R.id.settings_button)).setColorFilter(Color.WHITE);
428-
}
414+
// Set activity night mode. If NightMode.SYSTEM is set, then android will automatically
415+
// trigger recreation of activity when uiMode/dark mode configuration is changed so that
416+
// day or night theme takes affect.
417+
AppCompatActivityUtils.setNightMode(this, NightMode.getAppNightMode().getName(), true);
429418
}
430419

431420
private void setMargins() {
@@ -518,7 +507,7 @@ public void toggleTerminalToolbar() {
518507
private void saveTerminalToolbarTextInput(Bundle savedInstanceState) {
519508
if (savedInstanceState == null) return;
520509

521-
final EditText textInputView = findViewById(R.id.terminal_toolbar_text_input);
510+
final EditText textInputView = findViewById(R.id.terminal_toolbar_text_input);
522511
if (textInputView != null) {
523512
String textInput = textInputView.getText().toString();
524513
if (!textInput.isEmpty()) savedInstanceState.putString(ARG_TERMINAL_TOOLBAR_TEXT_INPUT, textInput);
@@ -934,12 +923,9 @@ private void reloadActivityStyling() {
934923
mTermuxService.setTerminalTranscriptRows();
935924

936925
// To change the activity and drawer theme, activity needs to be recreated.
937-
// But this will destroy the activity, and will call the onCreate() again.
938-
// We need to investigate if enabling this is wise, since all stored variables and
939-
// views will be destroyed and bindService() will be called again. Extra keys input
940-
// text will we restored since that has already been implemented. Terminal sessions
941-
// and transcripts are also already preserved. Theme does change properly too.
942-
// TermuxActivity.this.recreate();
926+
// It will destroy the activity, including all stored variables and views, and onCreate()
927+
// will be called again. Extra keys input text, terminal sessions and transcripts will be preserved.
928+
TermuxActivity.this.recreate();
943929
}
944930

945931

app/src/main/java/com/termux/app/activities/HelpActivity.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.termux.app.activities;
22

3-
import android.app.Activity;
43
import android.content.ActivityNotFoundException;
54
import android.content.Intent;
65
import android.net.Uri;
@@ -12,10 +11,12 @@
1211
import android.widget.ProgressBar;
1312
import android.widget.RelativeLayout;
1413

14+
import androidx.appcompat.app.AppCompatActivity;
15+
1516
import com.termux.shared.termux.TermuxConstants;
1617

1718
/** Basic embedded browser for viewing help pages. */
18-
public final class HelpActivity extends Activity {
19+
public final class HelpActivity extends AppCompatActivity {
1920

2021
WebView mWebView;
2122

app/src/main/java/com/termux/app/activities/SettingsActivity.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import android.os.Environment;
66

77
import androidx.annotation.NonNull;
8-
import androidx.appcompat.app.ActionBar;
98
import androidx.appcompat.app.AppCompatActivity;
109
import androidx.preference.Preference;
1110
import androidx.preference.PreferenceFragmentCompat;
@@ -24,24 +23,27 @@
2423
import com.termux.shared.android.AndroidUtils;
2524
import com.termux.shared.termux.TermuxConstants;
2625
import com.termux.shared.termux.TermuxUtils;
26+
import com.termux.shared.activity.media.AppCompatActivityUtils;
27+
import com.termux.shared.theme.NightMode;
2728

2829
public class SettingsActivity extends AppCompatActivity {
2930

3031
@Override
3132
protected void onCreate(Bundle savedInstanceState) {
3233
super.onCreate(savedInstanceState);
34+
35+
AppCompatActivityUtils.setNightMode(this, NightMode.getAppNightMode().getName(), true);
36+
3337
setContentView(R.layout.activity_settings);
3438
if (savedInstanceState == null) {
3539
getSupportFragmentManager()
3640
.beginTransaction()
3741
.replace(R.id.settings, new RootPreferencesFragment())
3842
.commit();
3943
}
40-
ActionBar actionBar = getSupportActionBar();
41-
if (actionBar != null) {
42-
actionBar.setDisplayHomeAsUpEnabled(true);
43-
actionBar.setDisplayShowHomeEnabled(true);
44-
}
44+
45+
AppCompatActivityUtils.setToolbar(this, com.termux.shared.R.id.toolbar);
46+
AppCompatActivityUtils.setShowBackButtonInActionBar(this, true);
4547
}
4648

4749
@Override

app/src/main/java/com/termux/filepicker/TermuxFileReceiverActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package com.termux.filepicker;
22

3-
import android.app.Activity;
43
import android.content.Intent;
54
import android.database.Cursor;
65
import android.net.Uri;
76
import android.provider.OpenableColumns;
87
import android.util.Patterns;
98

109
import androidx.annotation.NonNull;
10+
import androidx.appcompat.app.AppCompatActivity;
1111

1212
import com.termux.R;
1313
import com.termux.shared.data.DataUtils;
@@ -31,7 +31,7 @@
3131
import java.nio.charset.StandardCharsets;
3232
import java.util.regex.Pattern;
3333

34-
public class TermuxFileReceiverActivity extends Activity {
34+
public class TermuxFileReceiverActivity extends AppCompatActivity {
3535

3636
static final String TERMUX_RECEIVEDIR = TermuxConstants.TERMUX_FILES_DIR_PATH + "/home/downloads";
3737
static final String EDITOR_PROGRAM = TermuxConstants.TERMUX_HOME_DIR_PATH + "/bin/termux-file-editor";
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
12
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
23
android:layout_width="match_parent"
3-
android:layout_height="match_parent">
4+
android:layout_height="match_parent"
5+
android:orientation="vertical">
6+
7+
<include
8+
layout="@layout/partial_primary_toolbar"
9+
android:id="@+id/partial_primary_toolbar"/>
410

511
<FrameLayout
612
android:id="@+id/settings"
713
android:layout_width="match_parent"
814
android:layout_height="match_parent" />
15+
916
</LinearLayout>

app/src/main/res/layout/activity_termux.xml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<com.termux.app.terminal.TermuxActivityRootView xmlns:android="http://schemas.android.com/apk/res/android"
2+
xmlns:app="http://schemas.android.com/apk/res-auto"
23
android:id="@+id/activity_termux_root_view"
34
android:layout_width="match_parent"
45
android:layout_height="match_parent"
@@ -36,12 +37,12 @@
3637
android:layout_width="240dp"
3738
android:layout_height="match_parent"
3839
android:layout_gravity="start"
39-
android:background="@android:color/white"
4040
android:choiceMode="singleChoice"
4141
android:divider="@android:color/transparent"
4242
android:dividerHeight="0dp"
4343
android:descendantFocusability="blocksDescendants"
44-
android:orientation="vertical">
44+
android:orientation="vertical"
45+
android:background="?attr/termuxActivityDrawerBackground">
4546

4647
<LinearLayout
4748
android:layout_width="match_parent"
@@ -53,7 +54,8 @@
5354
android:layout_height="40dp"
5455
android:src="@drawable/ic_settings"
5556
android:background="@null"
56-
android:contentDescription="@string/action_open_settings" />
57+
android:contentDescription="@string/action_open_settings"
58+
app:tint="?attr/termuxActivityDrawerImageTint" />
5759
</LinearLayout>
5860

5961
<ListView
@@ -71,15 +73,15 @@
7173
android:layout_height="wrap_content"
7274
android:orientation="horizontal">
7375

74-
<Button
76+
<com.google.android.material.button.MaterialButton
7577
android:id="@+id/toggle_keyboard_button"
7678
style="?android:attr/buttonBarButtonStyle"
7779
android:layout_width="match_parent"
7880
android:layout_height="wrap_content"
7981
android:layout_weight="1"
8082
android:text="@string/action_toggle_soft_keyboard" />
8183

82-
<Button
84+
<com.google.android.material.button.MaterialButton
8385
android:id="@+id/new_session_button"
8486
style="?android:attr/buttonBarButtonStyle"
8587
android:layout_width="match_parent"

app/src/main/res/layout/item_terminal_sessions_list.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
1+
<com.google.android.material.textview.MaterialTextView xmlns:android="http://schemas.android.com/apk/res/android"
22
android:id="@+id/session_title"
33
android:layout_width="fill_parent"
44
android:layout_height="?android:attr/listPreferredItemHeight"
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<!--
4+
https://material.io/develop/android/theming/dark
5+
-->
6+
7+
<!-- TermuxActivity DayNight NoActionBar theme. -->
8+
<!-- See https://developer.android.com/training/material/theme.html for how to customize the Material theme. -->
9+
<!-- NOTE: Cannot use "Light." since it hides the terminal scrollbar on the default black background. -->
10+
<style name="Theme.TermuxActivity.DayNight.NoActionBar" parent="Theme.TermuxApp.DayNight.NoActionBar">
11+
<!-- Primary brand color. -->
12+
<item name="colorPrimary">@color/black</item>
13+
<item name="colorPrimaryVariant">@color/black</item>
14+
15+
<item name="android:windowBackground">@color/black</item>
16+
17+
<!-- Avoid action mode toolbar pushing down terminal content when
18+
selecting text on pre-6.0 (non-floating toolbar). -->
19+
<item name="android:windowActionModeOverlay">true</item>
20+
21+
<item name="android:windowTranslucentStatus">true</item>
22+
<item name="android:windowTranslucentNavigation">true</item>
23+
24+
<!-- https://developer.android.com/training/tv/start/start.html#transition-color -->
25+
<item name="android:windowAllowReturnTransitionOverlap">true</item>
26+
<item name="android:windowAllowEnterTransitionOverlap">true</item>
27+
28+
<!-- Left drawer. -->
29+
<item name="buttonBarButtonStyle">@style/TermuxActivity.Drawer.ButtonBarStyle.Dark</item>
30+
<item name="termuxActivityDrawerBackground">@color/black</item>
31+
<item name="termuxActivityDrawerImageTint">@color/white</item>
32+
33+
<!-- Extra keys colors. -->
34+
<item name="extraKeysButtonTextColor">@color/white</item>
35+
<item name="extraKeysButtonActiveTextColor">@color/red_400</item>
36+
<item name="extraKeysButtonBackgroundColor">@color/black</item>
37+
<item name="extraKeysButtonActiveBackgroundColor">@color/grey_500</item>
38+
</style>
39+
40+
</resources>

0 commit comments

Comments
 (0)