diff --git a/app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/CodeViewerScreen.kt b/app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/CodeViewerScreen.kt
index 650ac7d..c022267 100644
--- a/app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/CodeViewerScreen.kt
+++ b/app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/CodeViewerScreen.kt
@@ -147,6 +147,7 @@ private enum class ViewerLayout {
private val CompactHeightBreakpoint = 480.dp
private val SidePaneWidth = 288.dp
private val TreeIndent = 14.dp
+private val EdgeTabTouchWidth = 28.dp
private val NarrowSidePaneWidth = 220.dp
private val NarrowWideBreakpoint = 700.dp
@@ -376,8 +377,9 @@ fun CodeViewerScreen(
LocationStrip(enclosingSymbols(document.symbols, firstVisibleLine))
}
+ Box(Modifier.weight(1f).fillMaxWidth()) {
Row(
- Modifier.weight(1f).fillMaxWidth().openFromLeftEdge(enabled = !sidePaneIsShown && drawerState.isClosed) {
+ Modifier.fillMaxSize().openFromLeftEdge(enabled = !sidePaneIsShown && drawerState.isClosed) {
scope.launch { drawerState.open() }
},
) {
@@ -448,6 +450,12 @@ fun CodeViewerScreen(
}
}
}
+ // Says that there is something to draw out from this edge; without it nothing on the
+ // screen does.
+ if (!sidePaneIsShown) {
+ EdgeTab(Modifier.align(Alignment.CenterStart)) { scope.launch { drawerState.open() } }
+ }
+ }
if (layout != ViewerLayout.LANDSCAPE) Toolbar(tools)
}
}
@@ -835,6 +843,34 @@ private fun JumpToCounterpart(counterpart: RepositoryPath, modifier: Modifier =
}
}
+/**
+ * A small tab on the left edge, where the side pane is drawn out from. It can be tapped as well:
+ * a swipe from the edge is not available to everyone.
+ */
+@Composable
+private fun EdgeTab(modifier: Modifier = Modifier, onOpen: () -> Unit) {
+ val description = stringResource(R.string.codeviewer_edge_tab)
+ Box(
+ modifier
+ .size(width = EdgeTabTouchWidth, height = 72.dp)
+ .clickable(role = Role.Button, onClickLabel = description, onClick = onOpen)
+ .semantics { contentDescription = description },
+ contentAlignment = Alignment.CenterStart,
+ ) {
+ Box(
+ Modifier
+ .size(width = 14.dp, height = 56.dp)
+ .background(
+ MaterialTheme.colorScheme.primary.copy(alpha = 0.85f),
+ RoundedCornerShape(topEnd = 12.dp, bottomEnd = 12.dp),
+ ),
+ contentAlignment = Alignment.Center,
+ ) {
+ UBIcon(R.drawable.ic_ub_chevron_right, null, size = 14.dp, tint = MaterialTheme.colorScheme.onPrimary)
+ }
+ }
+}
+
/**
* A header and its source, side by side, header on the left whichever of the two was opened. The
* bar between them is dragged to give one side more of the width.
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
index b08f002..f210172 100644
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -1,14 +1,29 @@
-
+
+
+
+
+
+
+
+
+
+
+ android:fillColor="#1FFFFFFF"
+ android:pathData="M58,88 a34,34 0 1,0 68,0 a34,34 0 1,0 -68,0 Z" />
+
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
index ac4f04c..1e85468 100644
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ b/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -1,35 +1,41 @@
-
+
+
+
+
+ android:fillType="evenOdd"
+ android:pathData="M31.5,76 a9.5,9.5 0 1,0 19,0 a9.5,9.5 0 1,0 -19,0 Z M36.5,76 a4.5,4.5 0 1,0 9,0 a4.5,4.5 0 1,0 -9,0 Z" />
+ android:fillType="evenOdd"
+ android:pathData="M31.5,32 a9.5,9.5 0 1,0 19,0 a9.5,9.5 0 1,0 -19,0 Z M36.5,32 a4.5,4.5 0 1,0 9,0 a4.5,4.5 0 1,0 -9,0 Z" />
+ android:fillType="evenOdd"
+ android:pathData="M62.5,43 a9.5,9.5 0 1,0 19,0 a9.5,9.5 0 1,0 -19,0 Z M67.5,43 a4.5,4.5 0 1,0 9,0 a4.5,4.5 0 1,0 -9,0 Z" />
+
diff --git a/app/src/main/res/drawable/ic_launcher_monochrome.xml b/app/src/main/res/drawable/ic_launcher_monochrome.xml
index ead32bb..110608c 100644
--- a/app/src/main/res/drawable/ic_launcher_monochrome.xml
+++ b/app/src/main/res/drawable/ic_launcher_monochrome.xml
@@ -1,31 +1,41 @@
-
+
+
+
+
+ android:fillType="evenOdd"
+ android:pathData="M31.5,76 a9.5,9.5 0 1,0 19,0 a9.5,9.5 0 1,0 -19,0 Z M36.5,76 a4.5,4.5 0 1,0 9,0 a4.5,4.5 0 1,0 -9,0 Z" />
+ android:fillType="evenOdd"
+ android:pathData="M31.5,32 a9.5,9.5 0 1,0 19,0 a9.5,9.5 0 1,0 -19,0 Z M36.5,32 a4.5,4.5 0 1,0 9,0 a4.5,4.5 0 1,0 -9,0 Z" />
+ android:fillType="evenOdd"
+ android:pathData="M62.5,43 a9.5,9.5 0 1,0 19,0 a9.5,9.5 0 1,0 -19,0 Z M67.5,43 a4.5,4.5 0 1,0 9,0 a4.5,4.5 0 1,0 -9,0 Z" />
+
diff --git a/app/src/main/res/values/strings_codebrowser.xml b/app/src/main/res/values/strings_codebrowser.xml
index 55f75e1..99e6813 100644
--- a/app/src/main/res/values/strings_codebrowser.xml
+++ b/app/src/main/res/values/strings_codebrowser.xml
@@ -69,6 +69,7 @@
폴더 구조
클래스 · 함수
이 파일에는 표시할 클래스나 함수가 없습니다.
+ 폴더 구조와 클래스 · 함수 열기
위아래 바꾸기
펼쳐짐
접힘
diff --git a/docs/UBGitea_기술소개.pptx b/docs/UBGitea_기술소개.pptx
index c68267b..e47ecb7 100644
Binary files a/docs/UBGitea_기술소개.pptx and b/docs/UBGitea_기술소개.pptx differ
diff --git a/docs/development-log.md b/docs/development-log.md
index ba39339..ae7fc1a 100644
--- a/docs/development-log.md
+++ b/docs/development-log.md
@@ -1410,3 +1410,13 @@ This is the append-only implementation and handoff record shared by Codex and Cl
- Checks and results: the required checks pass; 437 unit tests, 0 failures; lint 0 errors.
- Live verification: installed on the SM-F966N; not seen on a screen by the implementer.
- Next owner: the product owner, to confirm on the device.
+
+## 2026-09-28 (continued) — TASK-061: a tab on the left edge, and a new app icon
+
+- Request: the human product owner asked for a mark showing that the side pane can be drawn out
+ from the left edge of the code, and for a more fitting app icon.
+- What changed: see `tasks/061-edge-tab-and-app-icon.md`.
+- Checks and results: the required checks pass; 437 unit tests, 0 failures; lint 0 errors.
+- Live verification: installed on the SM-F966N; neither change was seen on the device by the
+ implementer.
+- Next owner: the product owner, to confirm on the device.
diff --git a/tasks/061-edge-tab-and-app-icon.md b/tasks/061-edge-tab-and-app-icon.md
new file mode 100644
index 0000000..fdc94a7
--- /dev/null
+++ b/tasks/061-edge-tab-and-app-icon.md
@@ -0,0 +1,60 @@
+# TASK-061: A tab on the left edge, and a new app icon
+
+Status: implemented; required checks pass; installed on the product owner's Z Fold7, awaiting their confirmation
+Owner: Claude
+Reviewer: human product owner
+
+## Outcome
+
+Requested by the human product owner, 2026-09-28: nothing on the code screen said that the side
+pane could be drawn out from the left edge, and the app icon should be changed to suit the app.
+
+## Scope
+
+- Included:
+ 1. A small tab at the middle of the code's left edge, with an arrow. It marks where the pane is
+ drawn out from, and tapping it opens the pane as well. It is not shown where the pane is
+ already beside the code.
+ 2. App icon: the background is the app's bright sky blue running to its deeper primary (it was
+ a flat darker blue from before the redesign); the branch glyph's commits are drawn as rings.
+ The themed (monochrome) layer has the same shape.
+- Excluded: using the UbiSam logo in the icon. It is a wordmark, and unreadable at icon size.
+
+## Writable paths
+
+- `app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/CodeViewerScreen.kt`
+- `app/src/main/res/drawable/ic_launcher_*.xml`
+- `app/src/main/res/values/strings_codebrowser.xml`
+- `tasks/`, `docs/`
+
+## Acceptance criteria
+
+- [x] The tab has a spoken description and a touch area wider than what is drawn.
+- [x] The icon's glyph stays inside the 66dp safe circle of the adaptive icon.
+
+## Security and privacy
+
+No additional concerns.
+
+## Required checks
+
+```text
+./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug
+```
+
+## Evidence
+
+- Required checks pass: 437 unit tests, 0 failures; lint 0 errors.
+- Installed on the SM-F966N over wireless `adb`.
+- The icon was looked at only as a rough drawing made on a PC from the same coordinates, before
+ the glyph was made smaller to fit the safe circle; not on a launcher. The tab has not been seen
+ on a screen by the implementer.
+
+## Known limitations
+
+- The tab covers a strip 14dp wide and 56dp tall of the line numbers behind it.
+- A launcher may keep showing the old icon until it refreshes its cache.
+
+## Review findings
+
+None yet.