diff --git a/controller/app/src/main/AndroidManifest.xml b/controller/app/src/main/AndroidManifest.xml index 7d264777..12278a57 100644 --- a/controller/app/src/main/AndroidManifest.xml +++ b/controller/app/src/main/AndroidManifest.xml @@ -70,6 +70,17 @@ adjustPan, so the IME covered the ExtraKeys bar and the text stuck. adjustResize shrinks the window so the extra-keys bar + terminal sit above the keyboard. --> + + + { + terminalController.openFullTerminal(); + // Attach finish-on-hide only after the sheet has been expanded, so the initial + // HIDDEN state (set in bind()) can never reach a live callback and close the + // Activity on launch. Mirrors MainActivity, which attached it inside the open. + attachFinishOnHide(); + }; + if (root != null) root.post(open); + else open.run(); + } + + /** + * Swiping the terminal sheet down finishes back to the caller instead of exposing an + * empty surface. Mirrors MainActivity.attachTerminalOnlyFinish (ADFA-4987): no peek + * stop — a swipe-down goes straight to HIDDEN -> finish(). Attached once (after the + * first expand); a re-open via onNewIntent must not stack a second callback. + */ + private void attachFinishOnHide() { + if (finishOnHideAttached) return; + View sheet = findViewById(R.id.terminal_bottom_sheet); + if (sheet == null) return; + BottomSheetBehavior b = BottomSheetBehavior.from(sheet); + b.setHideable(true); + b.setSkipCollapsed(true); + b.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { + @Override + public void onStateChanged(@NonNull View bottomSheet, int newState) { + if (newState == BottomSheetBehavior.STATE_HIDDEN) { + finish(); + } + } + + @Override + public void onSlide(@NonNull View bottomSheet, float slideOffset) { } + }); + finishOnHideAttached = true; + } + + @Override + protected void onDestroy() { + // Release the terminal UI delegate so the app-scoped session store never holds a + // destroyed Activity; running sessions keep going (ADFA-4696). + if (terminalController != null) terminalController.detach(); + super.onDestroy(); + } + + // --- TerminalController.Host --------------------------------------------- + @Override + public void addToLog(String message) { + // Single source of truth; the Usage console observes LogRepository (ADFA-4640). + LogRepository.get().append(message); + } + + @Override + public void vibrateDevice() { + android.os.Vibrator v = (android.os.Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + if (v != null && v.hasVibrator()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + v.vibrate(android.os.VibrationEffect.createOneShot(50, android.os.VibrationEffect.DEFAULT_AMPLITUDE)); + } else { + v.vibrate(50); + } + } + } +} diff --git a/controller/app/src/main/java/org/iiab/controller/TerminalSessionService.java b/controller/app/src/main/java/org/iiab/controller/TerminalSessionService.java index e7a795e3..fbc9bbb8 100644 --- a/controller/app/src/main/java/org/iiab/controller/TerminalSessionService.java +++ b/controller/app/src/main/java/org/iiab/controller/TerminalSessionService.java @@ -93,11 +93,10 @@ CHANNEL_ID, getString(R.string.terminal_channel_name), } private Notification buildNotification() { - // Tapping the notification opens the terminal directly, bypassing the hidden - // version-footer gesture (ADFA-4696). SINGLE_TOP reuses the running Activity. - Intent open = new Intent(this, MainActivity.class) - .putExtra(MainActivity.EXTRA_OPEN_TERMINAL, true) - .putExtra(MainActivity.EXTRA_TERMINAL_ONLY, true) + // Tapping the notification opens the terminal directly (ADFA-4696). ADFA-5192: the terminal + // is its own Activity now, so no terminal-only extras are needed. SINGLE_TOP reuses the + // running instance. + Intent open = new Intent(this, TerminalActivity.class) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pending = PendingIntent.getActivity( this, 0, open, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/SettingsSubFragment.java b/controller/app/src/main/java/org/iiab/controller/redesign/SettingsSubFragment.java index 6761ee64..3570948d 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/SettingsSubFragment.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/SettingsSubFragment.java @@ -205,12 +205,9 @@ private void openAppSettings(Context ctx) { } catch (Exception ignore) { /* no-op */ } } - /** The full Debian terminal lives in MainActivity; EXTRA_OPEN_TERMINAL opens it directly. */ + /** The full Debian terminal lives in its own TerminalActivity (ADFA-5192). */ private void openTerminal(Context ctx) { - Intent i = new Intent(ctx, org.iiab.controller.MainActivity.class); - i.putExtra(org.iiab.controller.MainActivity.EXTRA_OPEN_TERMINAL, true); - i.putExtra(org.iiab.controller.MainActivity.EXTRA_TERMINAL_ONLY, true); - ctx.startActivity(i); + ctx.startActivity(new Intent(ctx, org.iiab.controller.TerminalActivity.class)); } // ---- Advanced (power-user features — preview for now) ---- diff --git a/controller/app/src/main/res/layout/terminal_activity.xml b/controller/app/src/main/res/layout/terminal_activity.xml new file mode 100644 index 00000000..5dd5b9c7 --- /dev/null +++ b/controller/app/src/main/res/layout/terminal_activity.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +