Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
08517c6
[chore] #3: navigation 모듈 생성
ikseong00 Dec 29, 2025
96f9b74
[chore] #3: compileSDK, targetSDK 36으로 업데이트
ikseong00 Dec 29, 2025
5f6e991
[feat] #3: 네비게이션 상태 및 컨트롤러 구현
ikseong00 Dec 29, 2025
9bc217e
[chore] #3: MainViewModel 클래스 제거
ikseong00 Dec 29, 2025
3e051cf
[chore] #3: app 모듈로 MainActivity 이동
ikseong00 Dec 29, 2025
6e2d694
[chore] #3: app 모듈의 중복된 의존성 제거
ikseong00 Dec 29, 2025
aad0b24
[feat] #3: app 모듈에 Compose, Navigation UI 종속성 추가
ikseong00 Dec 29, 2025
8dc8945
[feat] #3: feature-api 모듈 컨벤션 플러그인 추가
ikseong00 Dec 29, 2025
02f62fa
[chore] #3: android-feature 플러그인 android-feature-impl로 이름 변경
ikseong00 Dec 29, 2025
da173e7
[chore] #3: 프로젝트 build.gradle.kts 안드로이드 라이브러리 플러그인 추가
ikseong00 Dec 29, 2025
652b1f3
[feat] #3: pose.api, pose.impl 모듈 추가
ikseong00 Dec 29, 2025
35a21f8
[feat] #3: 포즈 NavKey, 네비게이션 이벤트 구현
ikseong00 Dec 29, 2025
c29ad1f
[refactor] #3: Navigator 인터페이스 형식으로 수정
ikseong00 Dec 29, 2025
a017482
[feat] #3: Navigator DI 설정 추가
ikseong00 Dec 29, 2025
5f8c58c
[feat] #3: EntryProviderInstaller 타입 추가
ikseong00 Dec 29, 2025
c20292d
[feat] #3: 포즈 EntryProvider 설정
ikseong00 Dec 29, 2025
41c750b
[feat] #3: archive.api, archive.impl 모듈 추가
ikseong00 Dec 29, 2025
99d6084
[feat] #3: 아카이빙 NavKey, 네비게이션 이벤트 구현
ikseong00 Dec 29, 2025
e31bfae
[feat] #3: 아카이빙 EntryProvider 설정
ikseong00 Dec 29, 2025
da0e31b
[feat] #3: map.api, map.impl 모듈 추가
ikseong00 Dec 29, 2025
5d250b2
[feat] #3: 네컷지도 Navkey, 네비게이션 이벤트 구현
ikseong00 Dec 29, 2025
6bfd314
[feat] #3: 네컷지도 EntryProvider 설정
ikseong00 Dec 29, 2025
ffc7f77
[refactor] #3: NavigatorImpl 대신 Navigator 인터페이스 사용하도록 변경
ikseong00 Dec 29, 2025
d8c636a
[chore] #3: Hilt 버전 업데이트 - 2.54
ikseong00 Dec 29, 2025
d1a9421
[refactor] #3: NavigationState Hilt를 통해 주입받도록 변경
ikseong00 Dec 29, 2025
71e7b1d
[refactor] #3: NavigatorModule 위치 변경 core:navigation -> app 모듈
ikseong00 Dec 29, 2025
5a58280
[feat] #3: NavDisplay 추가
ikseong00 Dec 29, 2025
a511341
[feat] #3: TopLevelNav 아이템 enum 정의
ikseong00 Dec 29, 2025
7c624df
[feat] #3: BottomNavigationBar 컴포저블 임시 구현
ikseong00 Dec 29, 2025
ae63072
[refactor] #3: TopLevelNavKey, StartKey를 Keys.kt로 통합
ikseong00 Dec 29, 2025
65cb0f4
[chore] #3: Entry Provider 모듈 이름 수정
ikseong00 Dec 29, 2025
954ab0a
[feat] #3: hilt-lifecycle-viewmodel-compose 의존성 추가
ikseong00 Dec 29, 2025
6318891
[feat] #3: hiltViewModel 에서 인자를 전달받는 예시 코드 구현
ikseong00 Dec 29, 2025
a4f0e7d
[chore] #3: 아카이브 모듈 패키지 이름 수정
ikseong00 Dec 29, 2025
b5af3af
[chore] #3: feature impl 모듈 사용하지 않는 의존성 제거
ikseong00 Dec 31, 2025
a3c011a
[chore] #3: NavigationModule, AppModule internal 키워드 추가
ikseong00 Dec 31, 2025
de190d3
[chore] #3: NavigatorImpl 생성자 파라미터 개행 추가
ikseong00 Dec 31, 2025
7538094
[feat] #3: NavigationState 에 ActivityRetainedScoped 적용
ikseong00 Dec 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
alias(libs.plugins.neki.android.application)
alias(libs.plugins.neki.android.application.compose)
}

android {
Expand All @@ -14,19 +15,21 @@ dependencies {
implementation(projects.core.common)
implementation(projects.core.dataApi)
implementation(projects.core.data)
implementation(projects.core.designsystem)
implementation(projects.core.domain)
implementation(projects.core.model)
implementation(projects.core.designsystem)
implementation(projects.core.navigation)
implementation(projects.feature.sample.impl)
implementation(projects.feature.sample.api)

implementation(projects.core.common)
implementation(projects.core.data)
implementation(projects.core.dataApi)
implementation(projects.core.designsystem)
implementation(projects.core.domain)
implementation(projects.core.model)
implementation(projects.feature.pose.api)
implementation(projects.feature.pose.impl)
implementation(projects.feature.archive.api)
implementation(projects.feature.archive.impl)
implementation(projects.feature.map.api)
implementation(projects.feature.map.impl)

implementation(libs.timber)

implementation(libs.androidx.activity.compose)
implementation(libs.androidx.navigation3.ui)
}
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
android:theme="@style/Theme.Neki">

<activity
android:name="com.neki.android.feature.sample.impl.MainActivity"
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
66 changes: 66 additions & 0 deletions app/src/main/java/com/neki/android/app/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.neki.android.app

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.ui.NavDisplay
import com.neki.android.app.ui.BottomNavigationBar
import com.neki.android.core.designsystem.ui.theme.NekiTheme
import com.neki.android.core.navigation.EntryProviderInstaller
import com.neki.android.core.navigation.NavigatorImpl
import com.neki.android.core.navigation.toEntries
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

@Inject
lateinit var navigator: NavigatorImpl

@Inject
lateinit var entryProviderScopes: Set<@JvmSuppressWildcards EntryProviderInstaller>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val shouldShowBottomBar by remember(navigator.state.currentKey) {
mutableStateOf(navigator.state.currentKey in navigator.state.topLevelKeys)
}
Comment thread
ikseong00 marked this conversation as resolved.

NekiTheme {
Scaffold(
modifier = Modifier.fillMaxSize(),
bottomBar = {
BottomNavigationBar(
visible = shouldShowBottomBar,
currentTab = navigator.state.currentTopLevelKey,
currentKey = navigator.state.currentKey,
onTabSelected = { navigator.navigate(it.navKey) },
)
}
) { innerPadding ->
NavDisplay(
modifier = Modifier.padding(innerPadding),
entries = navigator.state.toEntries(
entryProvider = entryProvider {
entryProviderScopes.forEach { builder -> this.builder() }
},
),
onBack = { navigator.goBack() },
)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.neki.android.app.navigation

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.navigation3.runtime.NavKey
import com.neki.android.app.R
import com.neki.android.feature.archive.api.ArchiveNavKey
import com.neki.android.feature.map.api.MapNavKey
import com.neki.android.feature.pose.api.PoseNavKey

enum class TopLevelNavItem(
@DrawableRes val selectedIcon: Int,
@DrawableRes val unselectedIcon: Int,
@StringRes val iconTextId: Int,
val navKey: NavKey,
) {
POSE_RECOMMEND(
selectedIcon = R.drawable.ic_nav_pose_selected,
unselectedIcon = R.drawable.ic_nav_pose_unselected,
iconTextId = R.string.top_level_nav_pose,
navKey = PoseNavKey.Pose,
),
ARCHIVE(
selectedIcon = R.drawable.ic_nav_archive_selected,
unselectedIcon = R.drawable.ic_nav_archive_unselected,
iconTextId = R.string.top_level_nav_archive,
navKey = ArchiveNavKey.Archive
),
MAP(
selectedIcon = R.drawable.ic_nav_map_selected,
unselectedIcon = R.drawable.ic_nav_map_unselected,
iconTextId = R.string.top_level_nav_map,
navKey = MapNavKey.Map
);

companion object {
val startTopLevelItem = ARCHIVE
}
}
18 changes: 18 additions & 0 deletions app/src/main/java/com/neki/android/app/navigation/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.neki.android.app.navigation.di

import com.neki.android.core.navigation.Navigator
import com.neki.android.core.navigation.NavigatorImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityRetainedComponent

@Module
@InstallIn(ActivityRetainedComponent::class)
internal interface AppModule {

@Binds
fun bindsNavigator(
impl: NavigatorImpl,
): Navigator
}
Comment thread
ikseong00 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.neki.android.app.navigation.di

import com.neki.android.app.navigation.keys.START_NAV_KEY
import com.neki.android.app.navigation.keys.TOP_LEVEL_NAV_KEYS
import com.neki.android.core.navigation.NavigationState
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityRetainedComponent
import dagger.hilt.android.scopes.ActivityRetainedScoped

@Module
@InstallIn(ActivityRetainedComponent::class)
internal object NavigationModule {

@Provides
@ActivityRetainedScoped
fun providesNavigationState(): NavigationState {
return NavigationState(
startKey = START_NAV_KEY,
topLevelKeys = TOP_LEVEL_NAV_KEYS.toSet(),
)
}
Comment thread
ikseong00 marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.neki.android.app.navigation.keys

import com.neki.android.app.navigation.TopLevelNavItem
import com.neki.android.feature.archive.api.ArchiveNavKey

internal val START_NAV_KEY = ArchiveNavKey.Archive
internal val TOP_LEVEL_NAV_KEYS = TopLevelNavItem.entries.map { it.navKey }
113 changes: 113 additions & 0 deletions app/src/main/java/com/neki/android/app/ui/BottomNavigationBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.neki.android.app.ui

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation3.runtime.NavKey
import com.neki.android.app.navigation.TopLevelNavItem
import com.neki.android.core.designsystem.ui.theme.NekiTheme

@Composable
fun BottomNavigationBar(
visible: Boolean,
currentKey: NavKey,
currentTab: NavKey,
tabs: List<TopLevelNavItem> = TopLevelNavItem.entries,
onTabSelected: (TopLevelNavItem) -> Unit,
) {
AnimatedVisibility(
visible = visible,
enter = slideInVertically { it },
exit = slideOutVertically { it },
Comment thread
ikseong00 marked this conversation as resolved.
) {
Surface(
modifier = Modifier
.navigationBarsPadding()
.fillMaxWidth(),
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
horizontalArrangement = Arrangement.spacedBy(2.5.dp)
) {
tabs.forEach { tab ->
BottomNavigationBarItem(
modifier = Modifier.weight(1f),
selected = tab.navKey == currentTab,
tab = tab,
onClick = { if (tab.navKey != currentKey) onTabSelected(tab) }
)
}
}
}
}
}

@Composable
fun BottomNavigationBarItem(
selected: Boolean,
tab: TopLevelNavItem,
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
) {
val icon = if (selected) tab.selectedIcon else tab.unselectedIcon
val color = if (selected) Color(0xFF3C3E48) else Color(0xFFB7B9C3)

Surface(
modifier = modifier,
onClick = onClick
) {
Column(
modifier = Modifier.padding(vertical = 8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Icon(
imageVector = ImageVector.vectorResource(icon),
contentDescription = stringResource(tab.iconTextId),
tint = color,
)
Text(
text = stringResource(tab.iconTextId),
color = color,
)
}
}
}

@Preview
@Composable
private fun BottomNavigationBarPreview() {
var currentTab by remember { mutableStateOf(TopLevelNavItem.ARCHIVE) }
NekiTheme {
BottomNavigationBar(
visible = true,
tabs = TopLevelNavItem.entries,
currentTab = currentTab.navKey,
currentKey = currentTab.navKey,
) { currentTab = it }
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_nav_archive_selected.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M23.333,2.334H7C5.593,2.334 3.5,3.266 3.5,5.834V22.167C3.5,24.735 5.593,25.667 7,25.667H24.5V23.334H7.014C6.475,23.32 5.833,23.108 5.833,22.167C5.833,21.227 6.475,21.015 7.014,21.001H24.5V3.501C24.5,3.191 24.377,2.894 24.158,2.676C23.94,2.457 23.643,2.334 23.333,2.334ZM11.087,5.834C11.552,5.834 11.998,6.019 12.327,6.348C12.656,6.676 12.84,7.122 12.84,7.587C12.84,8.053 12.656,8.499 12.327,8.827C11.998,9.156 11.552,9.341 11.087,9.341C10.622,9.341 10.176,9.156 9.847,8.827C9.518,8.499 9.333,8.053 9.333,7.587C9.333,7.122 9.518,6.676 9.847,6.348C10.176,6.019 10.622,5.834 11.087,5.834ZM14,15.167H8.167L11.667,11.667L13.417,13.3L16.917,9.334L21,15.167H14Z"
android:fillColor="#3C3E48"/>
Comment thread
ikseong00 marked this conversation as resolved.
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_nav_archive_unselected.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M23.333,2.334H7C5.593,2.334 3.5,3.266 3.5,5.834V22.167C3.5,24.735 5.593,25.667 7,25.667H24.5V23.334H7.014C6.475,23.32 5.833,23.108 5.833,22.167C5.833,21.227 6.475,21.015 7.014,21.001H24.5V3.501C24.5,3.191 24.377,2.894 24.158,2.676C23.94,2.457 23.643,2.334 23.333,2.334ZM11.087,5.834C11.552,5.834 11.998,6.019 12.327,6.348C12.656,6.676 12.84,7.122 12.84,7.587C12.84,8.053 12.656,8.499 12.327,8.827C11.998,9.156 11.552,9.341 11.087,9.341C10.622,9.341 10.176,9.156 9.847,8.827C9.518,8.499 9.333,8.053 9.333,7.587C9.333,7.122 9.518,6.676 9.847,6.348C10.176,6.019 10.622,5.834 11.087,5.834ZM14,15.167H8.167L11.667,11.667L13.417,13.3L16.917,9.334L21,15.167H14Z"
android:fillColor="#B7B9C3"/>
</vector>
16 changes: 16 additions & 0 deletions app/src/main/res/drawable/ic_nav_map_selected.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M14.307,21.814C16.072,20.897 22.166,17.304 22.166,11.333C22.166,10.239 21.951,9.155 21.532,8.144C21.113,7.133 20.499,6.214 19.725,5.441C18.951,4.667 18.033,4.053 17.022,3.634C16.011,3.216 14.927,3 13.833,3C12.739,3 11.655,3.216 10.644,3.634C9.633,4.053 8.714,4.667 7.941,5.441C7.167,6.214 6.553,7.133 6.134,8.144C5.716,9.155 5.5,10.239 5.5,11.333C5.5,17.304 11.594,20.898 13.359,21.814C13.505,21.89 13.668,21.93 13.833,21.93C13.998,21.93 14.16,21.89 14.307,21.814ZM13.833,14.904C14.78,14.904 15.689,14.528 16.358,13.858C17.028,13.189 17.404,12.28 17.404,11.333C17.404,10.386 17.028,9.477 16.358,8.808C15.689,8.138 14.78,7.762 13.833,7.762C12.886,7.762 11.977,8.138 11.308,8.808C10.638,9.477 10.262,10.386 10.262,11.333C10.262,12.28 10.638,13.189 11.308,13.858C11.977,14.528 12.886,14.904 13.833,14.904Z"
android:fillColor="#3C3E48"
android:fillType="evenOdd"/>
<path
android:pathData="M21.049,20.262C21.781,20.805 22.166,21.42 22.166,22.047C22.166,22.675 21.781,23.29 21.049,23.833C20.319,24.376 19.266,24.827 18,25.14C16.733,25.453 15.296,25.619 13.833,25.619C12.37,25.619 10.933,25.453 9.667,25.14C8.4,24.827 7.348,24.376 6.617,23.833C5.885,23.29 5.5,22.675 5.5,22.047C5.5,21.42 5.885,20.805 6.617,20.262"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#3C3E48"
android:strokeLineCap="round"/>
</vector>
16 changes: 16 additions & 0 deletions app/src/main/res/drawable/ic_nav_map_unselected.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M14.307,21.814C16.072,20.897 22.166,17.304 22.166,11.333C22.166,10.239 21.951,9.155 21.532,8.144C21.113,7.133 20.499,6.214 19.725,5.441C18.951,4.667 18.033,4.053 17.022,3.634C16.011,3.216 14.927,3 13.833,3C12.739,3 11.655,3.216 10.644,3.634C9.633,4.053 8.714,4.667 7.941,5.441C7.167,6.214 6.553,7.133 6.134,8.144C5.716,9.155 5.5,10.239 5.5,11.333C5.5,17.304 11.594,20.898 13.359,21.814C13.505,21.89 13.668,21.93 13.833,21.93C13.998,21.93 14.16,21.89 14.307,21.814ZM13.833,14.904C14.78,14.904 15.689,14.528 16.358,13.858C17.028,13.189 17.404,12.28 17.404,11.333C17.404,10.386 17.028,9.477 16.358,8.808C15.689,8.138 14.78,7.762 13.833,7.762C12.886,7.762 11.977,8.138 11.308,8.808C10.638,9.477 10.262,10.386 10.262,11.333C10.262,12.28 10.638,13.189 11.308,13.858C11.977,14.528 12.886,14.904 13.833,14.904Z"
android:fillColor="#B7B9C3"
android:fillType="evenOdd"/>
<path
android:pathData="M21.049,20.262C21.781,20.805 22.166,21.42 22.166,22.047C22.166,22.675 21.781,23.29 21.049,23.833C20.319,24.376 19.266,24.827 18,25.14C16.733,25.453 15.296,25.619 13.833,25.619C12.37,25.619 10.933,25.453 9.667,25.14C8.4,24.827 7.348,24.376 6.617,23.833C5.885,23.29 5.5,22.675 5.5,22.047C5.5,21.42 5.885,20.805 6.617,20.262"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#B7B9C3"
android:strokeLineCap="round"/>
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_nav_pose_selected.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M14.001,14.001C13.009,14.001 12.178,13.665 11.507,12.995C10.837,12.325 10.501,11.493 10.501,10.501C10.501,9.528 10.836,8.702 11.507,8.021C12.179,7.341 13.01,7.001 14.001,7.001C14.973,7.001 15.799,7.341 16.48,8.021C17.16,8.702 17.501,9.528 17.501,10.501C17.501,11.492 17.16,12.324 16.48,12.995C15.799,13.666 14.973,14.001 14.001,14.001ZM7.001,19.834V18.784C7.001,18.376 7.103,17.992 7.307,17.632C7.512,17.273 7.789,16.986 8.138,16.771C9.033,16.247 9.971,15.848 10.953,15.576C11.936,15.303 12.951,15.167 14.001,15.167C15.05,15.167 16.066,15.303 17.049,15.576C18.032,15.848 18.97,16.247 19.863,16.771C20.213,16.985 20.49,17.272 20.695,17.632C20.899,17.993 21.001,18.376 21.001,18.784V19.834C21.001,20.164 20.889,20.442 20.665,20.666C20.441,20.89 20.164,21.001 19.834,21.001H8.167C7.837,21.001 7.56,20.889 7.337,20.665C7.113,20.441 7.001,20.164 7.001,19.834ZM4.667,25.667C4.026,25.667 3.477,25.439 3.02,24.983C2.563,24.526 2.335,23.976 2.334,23.334V19.834C2.334,19.503 2.446,19.226 2.67,19.003C2.894,18.78 3.171,18.668 3.501,18.667C3.83,18.667 4.108,18.778 4.332,19.003C4.557,19.228 4.669,19.505 4.667,19.834V23.334H8.167C8.498,23.334 8.775,23.446 8.999,23.67C9.223,23.894 9.335,24.171 9.334,24.501C9.333,24.83 9.221,25.108 8.998,25.333C8.775,25.557 8.498,25.669 8.167,25.667H4.667ZM2.334,8.167V4.667C2.334,4.026 2.563,3.477 3.02,3.02C3.477,2.563 4.026,2.335 4.667,2.334H8.167C8.498,2.334 8.775,2.446 8.999,2.67C9.223,2.894 9.335,3.171 9.334,3.501C9.333,3.83 9.221,4.108 8.998,4.332C8.775,4.557 8.498,4.669 8.167,4.667H4.667V8.167C4.667,8.498 4.555,8.775 4.331,8.999C4.107,9.223 3.83,9.335 3.501,9.334C3.171,9.333 2.894,9.221 2.67,8.998C2.446,8.775 2.334,8.498 2.334,8.167ZM23.334,25.667H19.834C19.503,25.667 19.226,25.555 19.003,25.331C18.78,25.107 18.668,24.83 18.667,24.501C18.667,24.171 18.778,23.894 19.003,23.67C19.228,23.446 19.505,23.334 19.834,23.334H23.334V19.834C23.334,19.503 23.446,19.226 23.67,19.003C23.894,18.78 24.171,18.668 24.501,18.667C24.83,18.667 25.108,18.778 25.333,19.003C25.557,19.228 25.669,19.505 25.667,19.834V23.334C25.667,23.976 25.439,24.525 24.983,24.983C24.526,25.44 23.976,25.668 23.334,25.667ZM23.334,8.167V4.667H19.834C19.503,4.667 19.226,4.555 19.003,4.331C18.78,4.107 18.668,3.83 18.667,3.501C18.667,3.171 18.778,2.894 19.003,2.67C19.228,2.446 19.505,2.334 19.834,2.334H23.334C23.976,2.334 24.525,2.563 24.983,3.02C25.44,3.477 25.668,4.026 25.667,4.667V8.167C25.667,8.498 25.555,8.775 25.331,8.999C25.107,9.223 24.83,9.335 24.501,9.334C24.171,9.333 23.894,9.221 23.67,8.998C23.446,8.775 23.334,8.498 23.334,8.167Z"
android:fillColor="#3C3E48"/>
</vector>
Loading