From 17fa2480659a8accd9a2fda6ee9960014fcf2cf3 Mon Sep 17 00:00:00 2001 From: choiminyeong Date: Mon, 28 Sep 2026 16:31:27 +0900 Subject: [PATCH] TASK-061: edge tab for the side pane, and a new app icon Co-Authored-By: Claude Fable 5.1 --- .../feature/codebrowser/CodeViewerScreen.kt | 38 ++++++++++- .../res/drawable/ic_launcher_background.xml | 27 ++++++-- .../res/drawable/ic_launcher_foreground.xml | 34 ++++++---- .../res/drawable/ic_launcher_monochrome.xml | 30 ++++++--- .../main/res/values/strings_codebrowser.xml | 1 + docs/UBGitea_기술소개.pptx | Bin 725853 -> 725853 bytes docs/development-log.md | 10 +++ tasks/061-edge-tab-and-app-icon.md | 60 ++++++++++++++++++ 8 files changed, 169 insertions(+), 31 deletions(-) create mode 100644 tasks/061-edge-tab-and-app-icon.md 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 c68267b4b73b80b809076126edd89cc2ce617e24..e47ecb75d078f15d5cd529e2423750f5a09cd752 100644 GIT binary patch delta 2748 zcmY*Zdr(wm6zAT%_wMEUchEPW~L@;WJVcSL|VQwC!K_ROgV;S zv@P@%S#B9RnUSXqj4Lia0&2ofcQ*xoqb<-!+RrIQRR`IltfUoV)jT zZl~+qP8XdsQ?ZaJ{ul7jQBuH@J{tZ#FhUA=m&r~~jSWt|+u+nBIXxGgaO!r6oHtK` zB-{`4J}D)@(*>0|{TCC`X_(65I8Luiwu>H?x>?r$SGi0cgDIzXj|@Bj=k)$8 zC&5#XoC^QPD49~g|F9BC;UR64452OKpj8j#<~{Oiab=T#*Myg3HPfAQN47UBcaHf~ zoeR|dgSofHL%1|!AQ?jYlBIBBE3XlUzq~R>0`zyQeubM3e)Hz@GZkLDA;2k4zOX@x z;}mvfVafEwsHo|Qtl*S1*uQ$ygNcwo?yHkgLRx*jhn)|}qy4Y%*skH#{+t2}>!^`k z{)*k_fyF;{&%t{zv-ytHMmGDXG}52id68#qT`d}fbKwL|8jOU>vCcPNPsciTsFx6y zTdQUptvmGf68o+~8Yu;gV1>jRjRQ+1-f6Thm)1NC@t&g+6}nch+7>}wEVNuIFp^K| zR5iXkAr%9yG2(k{V@>_UVN5$ERn9}&pgL|l(i(rI$XuUs+$AH=woDm$J{c!JIv4Kk zn`O#*ld47ja*fD`J@T0#@_6g zheKC$zbuzR-2aebPVr>IzF))?!zIw)vp}hbv6)+<4i>JFlZ|i66~1C)SA{ZcE)v;y zO}s@65%^reAzGUi9O9ir3J$UN3uX8s=xM#p63d79CB<@#FY{x!Wsr<7ebbP@zRGn` zQI+f1(+4b09{V{xi{0v>!U)zWjjY&L<$gGfG9ok8V{Faji?md`+7A z+5*tsq=D`srJB>2@v_>^b*F6=m0>SbB6t1|4O#O_qN3)N2=4K3sE?OG<=cM)Hcq&y zKH~uM|+xtyxA2k zn)zm#c3K+^?Ww1=A`VlPW5wlc$+I34l!Xb?oq}@f6f06LpK3j_1&1sN99qm`OSMr( zX{)te!n^vu!P^A=(toUt%Jl;!h!0YM(WSjFWpj>cSP-2w)cK{8nb;RFE)hFWe7|X`#D4;T1$G0rd=Vze9iV({>|Mbz>}CQM8NK@ zw~rO5**9(oI~=+J7zuGeHs&hHhfr~qOo8y>RWcdE<*TT*EyKaacaju*q1?aO;!Xm9 z%-2cog%Ic@1rXA&VF0h52&cW*5CVLfpE9~g5rp+!1ilM)wu=-(7}iZ@L3pa0+>6j? z!VCM!VD>{d$$?CK4=Kb9ny`BSGAnvW24s9ag1Lvxhtt$vvkpxd>l%7V2DZ+mRY%y$ zZfFhll61VfGp6J$L!QZf$Wz&edJguXo|t~b2E%o*rTv8O6--wMLAyl)d)Oqn)I5KJ zASerybSSO~qp07)2nx3AVEF?i2dNzw*M205>jq3U`Bk+)3N;s@3i^{G*tjr)Y8oS` zrZ2)l>x!w+G5*WM2F7*N`Kg!_Z5QX1B+6xg;qu*7OO)@rMWTGyLuD#U{&wQieauJcV3w>8lo-JkN`Xwem!qk z5xU5V(7UXd`qRo&EJvraP%4@#LNw?I0iG)6+MeRMPe>??HYK33;#{6+QvzBl_MeZ& z{zQU2WdwN|32Nvks9_$(+*_0uA^9_hlhVXUYK)18eu;R+F^E?aW9mV-#61UNOg(6p zsAp0v?isw&!2%ZW=&i9d7dg0TvesD2-6A#)MJ3_4h62r7YlyqV6${k5U`=7o9)Q5#*XQ)?UaAe$q9H`k$|Uf6Da>^ I;v97LKPvb!`v3p{ delta 2747 zcmY*Zdr(wm6zAT%_wMEU7T9GSH$@U(ShTzpMR}-TW@@5lW~70Iq~$v&orHW$Ii_W_ zt@ssLZW%e5k+e;h(eaUuIyt0hnp$IuI6W+;#T9uj+xgCS&EgNv{l0U~@Ao_B?)_c< z#C`b_H=RC3v5*M%`*AlbZ2WS6JH4kzDzaH^GDo~tf6wYx>mn%g7ow!kdvj-F(`d z4b=Wa*+XI=T%X*N0HJBoVmPrCw~5nVQkEqF`UmB|!c7amdFSOR3a?$?%qh;kvR;bj z6b@xx;iR~Th)HoQ@4VF8ziQ(XagaaltCUefN>!DIT?xvG{7FaV;-9eh(8HM7G%UG>O*<(K^e4Ao;~9Hfy$0cOD3+53!od=(^Uc;%v5pjlYs)uFp8_mXT-2a2a{N7$HAB1MVH0 zWXgHtH;ep@3XuxAGElPUx!<^tc8jdUy6=(Ux|)_1JD8YB?m2|pN07TAQcfm8=@lO8n=r1iWK#& zxuCmN1KoX!G?y{?b+w7>PT49dLtdyv?%Z?L8M6u_B4!l|?vdNo`GrvV-rsgJ+x+2(AShM=;tKYWci5yZ%n|Rr=!}f_e2R&16<0kG+I_Yz&1ryR2R_ z-z?KEXo=9Cd_gPVFy&cRT+Wsp>nTB*A3MnzX5T&N-jcV_Xh}gAA2f5Mnc#YAn6bm1xY+>3Xs0=+!G+9z{F}L zCmS0CpLnc=41nuZEhOhoWkU;4m>_GxuhOi^SyMW;!2V_HUkz5F+x5#)1pWY(lAl$fxS{u`xY-B4*!uQGTn=Nc50LXl; zTL{Q)nnka?>0h!P4iP)8!3RWu8qKF!7jCtdx06Q@8a;Sk zH|fpJwUaE!#B`8+%%BIS_dsS@2T6mBuR}0*klApW&}r782V-4zCrQKBDYX0;ThR`! z!A_EjSEFr(ml*Pl>q4HgF4S|V3-#E#5gYv0$rg7LzE|*EAq3qP2^=Al;CkKcQG%d2 zL{g!+B7~xT3n3`Du9M~VkSwHjUR(2-D6Z@=)#R3M`%$R52361>AI8RcVN_ESMm1ew z4q7>r3LPVl##J+}qtZ{soankZrzBA>1N@fnX0t^3uInYrcimT}V%O<^eS2K6zA97B zdRV68QQ~iBzTD4zl=fx`3QfnWX?3AqEKi54WeUahEA$EI=};*DwSdDq*>nrdhUYgd z$n%p03x=yE=}=ZBoq{9(v~0dsw3dc+xdQTcRNWSTOv0wp$Up zz>3hjt(f}L%2O;$r&CcXdMZLx>j(jsD(2dmDCu4YvaEJs`nZGg4>}