Navigation bars

This commit is contained in:
tom5079
2024-02-20 11:52:52 -08:00
parent 72b0fa78bb
commit b0fedd78fb
11 changed files with 433 additions and 63 deletions

View File

@@ -92,9 +92,12 @@ dependencies {
implementation 'androidx.compose.material:material-icons-extended' implementation 'androidx.compose.material:material-icons-extended'
implementation 'androidx.activity:activity-compose:1.8.2' implementation 'androidx.activity:activity-compose:1.8.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.7.0'
implementation "com.google.accompanist:accompanist-adaptive:0.34.0" implementation "com.google.accompanist:accompanist-adaptive:0.34.0"
implementation "androidx.navigation:navigation-compose:2.7.7" implementation "androidx.navigation:navigation-compose:2.7.7"
kapt 'androidx.lifecycle:lifecycle-compiler:2.7.0'
implementation "androidx.paging:paging-compose:3.2.1" implementation "androidx.paging:paging-compose:3.2.1"
implementation "io.ktor:ktor-client-core:2.3.8" implementation "io.ktor:ktor-client-core:2.3.8"

View File

@@ -24,8 +24,10 @@ import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.accompanist.adaptive.calculateDisplayFeatures import com.google.accompanist.adaptive.calculateDisplayFeatures
import xyz.quaver.pupil.ui.composable.PupilApp import xyz.quaver.pupil.ui.composable.MainApp
import xyz.quaver.pupil.ui.theme.AppTheme import xyz.quaver.pupil.ui.theme.AppTheme
import xyz.quaver.pupil.ui.viewmodel.MainViewModel import xyz.quaver.pupil.ui.viewmodel.MainViewModel
@@ -42,10 +44,13 @@ class MainActivity : BaseActivity() {
val windowSize = calculateWindowSizeClass(this) val windowSize = calculateWindowSizeClass(this)
val displayFeatures = calculateDisplayFeatures(this) val displayFeatures = calculateDisplayFeatures(this)
PupilApp( val uiState by viewModel.uiState.collectAsStateWithLifecycle()
MainApp(
windowSize = windowSize, windowSize = windowSize,
displayFeatures = displayFeatures, displayFeatures = displayFeatures,
uiState = viewModel.uiState uiState = uiState,
navigateToDestination = viewModel::navigateToDestination
) )
} }
} }

View File

@@ -0,0 +1,10 @@
package xyz.quaver.pupil.ui.composable
import androidx.compose.runtime.Composable
@Composable
fun GalleryList(
) {
}

View File

@@ -1,6 +1,14 @@
package xyz.quaver.pupil.ui.composable package xyz.quaver.pupil.ui.composable
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.DrawerValue import androidx.compose.material3.DrawerValue
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.PermanentNavigationDrawer import androidx.compose.material3.PermanentNavigationDrawer
import androidx.compose.material3.rememberDrawerState import androidx.compose.material3.rememberDrawerState
import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
@@ -8,16 +16,18 @@ import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.navigation.compose.rememberNavController import androidx.compose.ui.Modifier
import androidx.window.layout.DisplayFeature import androidx.window.layout.DisplayFeature
import androidx.window.layout.FoldingFeature import androidx.window.layout.FoldingFeature
import kotlinx.coroutines.launch
import xyz.quaver.pupil.ui.viewmodel.MainUIState import xyz.quaver.pupil.ui.viewmodel.MainUIState
@Composable @Composable
fun PupilApp( fun MainApp(
windowSize: WindowSizeClass, windowSize: WindowSizeClass,
displayFeatures: List<DisplayFeature>, displayFeatures: List<DisplayFeature>,
uiState: MainUIState uiState: MainUIState,
navigateToDestination: (MainDestination) -> Unit
) { ) {
val navigationType: NavigationType val navigationType: NavigationType
val contentType: ContentType val contentType: ContentType
@@ -31,7 +41,7 @@ fun PupilApp(
when (windowSize.widthSizeClass) { when (windowSize.widthSizeClass) {
WindowWidthSizeClass.Compact -> { WindowWidthSizeClass.Compact -> {
navigationType = NavigationType.NAVIGATION_RAIL navigationType = NavigationType.BOTTOM_NAVIGATION
contentType = ContentType.SINGLE_PANE contentType = ContentType.SINGLE_PANE
} }
WindowWidthSizeClass.Medium -> { WindowWidthSizeClass.Medium -> {
@@ -51,7 +61,7 @@ fun PupilApp(
contentType = ContentType.DUAL_PANE contentType = ContentType.DUAL_PANE
} }
else -> { else -> {
navigationType = NavigationType.NAVIGATION_RAIL navigationType = NavigationType.BOTTOM_NAVIGATION
contentType = ContentType.SINGLE_PANE contentType = ContentType.SINGLE_PANE
} }
} }
@@ -63,30 +73,113 @@ fun PupilApp(
else -> NavigationContentPosition.TOP else -> NavigationContentPosition.TOP
} }
PupilNavigationWrapper( MainNavigationWrapper(
navigationType, navigationType,
contentType, contentType,
navigationContentPosition displayFeatures,
navigationContentPosition,
uiState,
navigateToDestination
) )
} }
@Composable @Composable
private fun PupilNavigationWrapper( private fun MainNavigationWrapper(
navigationType: NavigationType, navigationType: NavigationType,
contentType: ContentType, contentType: ContentType,
navigationContentPosition: NavigationContentPosition displayFeatures: List<DisplayFeature>,
navigationContentPosition: NavigationContentPosition,
uiState: MainUIState,
navigateToDestination: (MainDestination) -> Unit
) { ) {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val openDrawer: () -> Unit = {
coroutineScope.launch {
drawerState.open()
}
}
if (navigationType == NavigationType.PERMANENT_NAVIGATION_DRAWER) { if (navigationType == NavigationType.PERMANENT_NAVIGATION_DRAWER) {
PermanentNavigationDrawer(drawerContent = { PermanentNavigationDrawer(drawerContent = {
PermanentNavigationDrawerContent( PermanentNavigationDrawerContent(
navigationContentPosition = navigationContentPosition selectedDestination = uiState.currentDestination,
navigationContentPosition = navigationContentPosition,
navigateToDestination = navigateToDestination
) )
}) { }) {
// PupilMain() MainContent(
navigationType = navigationType,
contentType = contentType,
displayFeatures = displayFeatures,
navigationContentPosition = navigationContentPosition,
uiState = uiState,
navigateToDestination = navigateToDestination,
onDrawerClicked = openDrawer
)
}
} else {
ModalNavigationDrawer(
drawerContent = {
ModalNavigationDrawerContent(
selectedDestination = uiState.currentDestination,
navigationContentPosition = navigationContentPosition,
navigateToDestination = navigateToDestination,
onDrawerClicked = {
coroutineScope.launch {
drawerState.close()
}
}
)
},
drawerState = drawerState
) {
MainContent(
navigationType = navigationType,
contentType = contentType,
displayFeatures = displayFeatures,
navigationContentPosition = navigationContentPosition,
uiState = uiState,
navigateToDestination = navigateToDestination,
onDrawerClicked = openDrawer
)
}
}
}
@Composable
fun MainContent(
navigationType: NavigationType,
contentType: ContentType,
displayFeatures: List<DisplayFeature>,
navigationContentPosition: NavigationContentPosition,
uiState: MainUIState,
navigateToDestination: (MainDestination) -> Unit,
onDrawerClicked: () -> Unit
) {
Row(modifier = Modifier.fillMaxSize()) {
AnimatedVisibility(visible = navigationType == NavigationType.NAVIGATION_RAIL) {
MainNavigationRail(
selectedDestination = uiState.currentDestination,
navigationContentPosition = navigationContentPosition,
navigateToDestination = navigateToDestination,
onDrawerClicked = onDrawerClicked
)
}
Column(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.inverseOnSurface)
) {
Box(modifier = Modifier.weight(1f))
AnimatedVisibility(visible = navigationType == NavigationType.BOTTOM_NAVIGATION) {
BottomNavigationBar(
selectedDestination = uiState.currentDestination,
navigateToDestination = navigateToDestination
)
}
} }
} }
} }

View File

@@ -2,37 +2,46 @@ package xyz.quaver.pupil.ui.composable
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Download import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.History import androidx.compose.material.icons.filled.History
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Star import androidx.compose.material.icons.filled.Star
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
data class MainDestination( sealed interface MainDestination {
val route: String, val route: String
val icon: ImageVector, val icon: ImageVector
val textId: Int val textId: Int
)
object Search: MainDestination {
override val route = "search"
override val icon = Icons.Default.Search
override val textId = R.string.main_destination_search
}
object History: MainDestination {
override val route = "history"
override val icon = Icons.Default.History
override val textId = R.string.main_destination_history
}
object Downloads: MainDestination {
override val route = "downloads"
override val icon = Icons.Default.Download
override val textId = R.string.main_destination_downloads
}
object Favorites: MainDestination {
override val route = "favorites"
override val icon = Icons.Default.Favorite
override val textId = R.string.main_destination_favorites
}
}
val mainDestinations = listOf( val mainDestinations = listOf(
MainDestination( MainDestination.Search,
"search", MainDestination.History,
Icons.Default.Search, MainDestination.Downloads,
R.string.main_destination_search MainDestination.Favorites
),
MainDestination(
"history",
Icons.Default.History,
R.string.main_destination_history
),
MainDestination(
"downloads",
Icons.Default.Download,
R.string.main_destination_downloads
),
MainDestination(
"favorites",
Icons.Default.Star,
R.string.main_destination_favorites
),
) )

View File

@@ -4,56 +4,289 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.MenuOpen
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.MenuOpen
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.PermanentDrawerSheet import androidx.compose.material3.PermanentDrawerSheet
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasurePolicy
import androidx.compose.ui.layout.layout
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.offset
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
@Composable @Composable
fun PermanentNavigationDrawerContent( fun PermanentNavigationDrawerContent(
navigationContentPosition: NavigationContentPosition selectedDestination: MainDestination,
navigationContentPosition: NavigationContentPosition,
navigateToDestination: (MainDestination) -> Unit
) { ) {
PermanentDrawerSheet( PermanentDrawerSheet(
modifier = Modifier.sizeIn(minWidth = 200.dp, maxWidth = 300.dp), modifier = Modifier.sizeIn(minWidth = 200.dp, maxWidth = 300.dp),
drawerContainerColor = MaterialTheme.colorScheme.inverseOnSurface drawerContainerColor = MaterialTheme.colorScheme.inverseOnSurface
) { ) {
Column( Layout(
modifier = Modifier modifier = Modifier
.background(MaterialTheme.colorScheme.inverseOnSurface) .background(MaterialTheme.colorScheme.inverseOnSurface)
.padding(16.dp) .padding(16.dp),
) { content = {
Row( Row(
verticalAlignment = Alignment.CenterVertically modifier = Modifier.layoutId(LayoutType.HEADER),
) { verticalAlignment = Alignment.CenterVertically
) {
Icon(
modifier = Modifier.size(32.dp),
painter = painterResource(R.drawable.app_icon),
tint = Color.Unspecified,
contentDescription = "app icon"
)
Text(
modifier = Modifier.padding(16.dp),
text = "Pupil",
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.Bold),
color = MaterialTheme.colorScheme.primary
)
}
Column(
modifier = Modifier
.layoutId(LayoutType.CONTENT)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
mainDestinations.forEach { destination ->
NavigationDrawerItem(
label = {
Text(
text = stringResource(destination.textId),
modifier = Modifier.padding(16.dp)
)
},
icon = {
Icon(
imageVector = destination.icon,
contentDescription = stringResource(destination.textId)
)
},
selected = selectedDestination.route == destination.route,
colors = NavigationDrawerItemDefaults.colors(
unselectedContainerColor = Color.Transparent
),
onClick = { navigateToDestination(destination) }
)
}
}
},
measurePolicy = navigationMeasurePolicy(navigationContentPosition)
)
}
}
@Composable
fun ModalNavigationDrawerContent(
selectedDestination: MainDestination,
navigationContentPosition: NavigationContentPosition,
navigateToDestination: (MainDestination) -> Unit,
onDrawerClicked: () -> Unit
) {
ModalDrawerSheet {
Layout(
modifier = Modifier
.background(MaterialTheme.colorScheme.inverseOnSurface)
.padding(16.dp),
content = {
Row(
modifier = Modifier
.layoutId(LayoutType.HEADER)
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
modifier = Modifier.size(32.dp),
painter = painterResource(R.drawable.app_icon),
tint = Color.Unspecified,
contentDescription = "app icon"
)
Text(
modifier = Modifier.padding(16.dp),
text = "Pupil",
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.Bold),
color = MaterialTheme.colorScheme.primary
)
}
IconButton(onClick = onDrawerClicked) {
Icon(
imageVector = Icons.AutoMirrored.Default.MenuOpen,
contentDescription = stringResource(R.string.main_open_navigation_drawer)
)
}
}
Column (
modifier = Modifier
.layoutId(LayoutType.CONTENT)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
mainDestinations.forEach { destination ->
NavigationDrawerItem(
label = {
Text(
text = stringResource(destination.textId),
modifier = Modifier.padding(16.dp)
)
},
icon = {
Icon(
imageVector = destination.icon,
contentDescription = stringResource(destination.textId)
)
},
selected = selectedDestination.route == destination.route,
colors = NavigationDrawerItemDefaults.colors(
unselectedContainerColor = Color.Transparent
),
onClick = { navigateToDestination(destination) }
)
}
}
},
measurePolicy = navigationMeasurePolicy(navigationContentPosition)
)
}
}
@Composable
fun MainNavigationRail(
selectedDestination: MainDestination,
navigationContentPosition: NavigationContentPosition,
navigateToDestination: (MainDestination) -> Unit,
onDrawerClicked: () -> Unit
) {
NavigationRail (
modifier = Modifier.fillMaxHeight(),
containerColor = MaterialTheme.colorScheme.inverseOnSurface
) {
NavigationRailItem(
selected = false,
onClick = onDrawerClicked,
icon = {
Icon( Icon(
modifier = Modifier.size(32.dp), imageVector = Icons.Default.Menu,
painter = painterResource(R.drawable.app_icon), contentDescription = stringResource(R.string.main_open_navigation_drawer)
tint = Color.Unspecified,
contentDescription = "app icon"
) )
Text( }
modifier = Modifier.padding(16.dp), )
text = "Pupil",
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.Bold), Column(
color = MaterialTheme.colorScheme.primary modifier = Modifier.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
mainDestinations.forEach { destination ->
NavigationRailItem(
selected = selectedDestination.route == destination.route,
onClick = { navigateToDestination(destination) },
icon = {
Icon(
imageVector = destination.icon,
contentDescription = stringResource(destination.textId)
)
}
) )
} }
} }
Column( }
}
) { @Composable
Text("Help") fun BottomNavigationBar(
selectedDestination: MainDestination,
navigateToDestination: (MainDestination) -> Unit
) {
NavigationBar(modifier = Modifier.fillMaxWidth()) {
mainDestinations.forEach { destination ->
NavigationBarItem(
selected = selectedDestination.route == destination.route,
onClick = { navigateToDestination(destination) },
icon = {
Icon(
imageVector = destination.icon,
contentDescription = stringResource(destination.textId)
)
}
)
} }
} }
} }
fun navigationMeasurePolicy(
navigationContentPosition: NavigationContentPosition,
): MeasurePolicy {
return MeasurePolicy { measurables, constraints ->
lateinit var headerMeasurable: Measurable
lateinit var contentMeasurable: Measurable
measurables.forEach {
when (it.layoutId) {
LayoutType.HEADER -> headerMeasurable = it
LayoutType.CONTENT -> contentMeasurable = it
else -> error("Unknown layoutId encountered!")
}
}
val headerPlaceable = headerMeasurable.measure(constraints)
val contentPlaceable = contentMeasurable.measure(
constraints.offset(vertical = -headerPlaceable.height)
)
layout(constraints.maxWidth, constraints.maxHeight) {
headerPlaceable.placeRelative(0, 0)
val nonContentVerticalSpace = constraints.maxHeight - contentPlaceable.height
val contentPlaceableY = when (navigationContentPosition) {
NavigationContentPosition.TOP -> 0
NavigationContentPosition.CENTER -> nonContentVerticalSpace / 2
}.coerceAtLeast(headerPlaceable.height)
contentPlaceable.placeRelative(0, contentPlaceableY)
}
}
}
enum class LayoutType {
HEADER, CONTENT
}

View File

@@ -1,5 +1,5 @@
package xyz.quaver.pupil.ui.composable package xyz.quaver.pupil.ui.composable
enum class NavigationType { enum class NavigationType {
NAVIGATION_RAIL, PERMANENT_NAVIGATION_DRAWER NAVIGATION_RAIL, PERMANENT_NAVIGATION_DRAWER, BOTTOM_NAVIGATION
} }

View File

@@ -1,14 +1,25 @@
package xyz.quaver.pupil.ui.viewmodel package xyz.quaver.pupil.ui.viewmodel
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import xyz.quaver.pupil.networking.SearchQuery import xyz.quaver.pupil.networking.SearchQuery
import xyz.quaver.pupil.ui.composable.MainRoutes import xyz.quaver.pupil.ui.composable.MainDestination
import xyz.quaver.pupil.ui.composable.mainDestinations
class MainViewModel : ViewModel() { class MainViewModel : ViewModel() {
val uiState: MainUIState = MainUIState() private val _uiState = MutableStateFlow(MainUIState())
val uiState: StateFlow<MainUIState> = _uiState
fun navigateToDestination(destination: MainDestination) {
_uiState.value = MainUIState(
currentDestination = destination
)
}
} }
data class MainUIState( data class MainUIState(
val route: MainRoutes = MainRoutes.SEARCH, val currentDestination: MainDestination = mainDestinations.first(),
val query: SearchQuery? = null val query: SearchQuery? = null,
val loading: Boolean = true
) )

View File

@@ -33,6 +33,7 @@
<string name="default_query_dialog_filter_guro">グロフィルター</string> <string name="default_query_dialog_filter_guro">グロフィルター</string>
<string name="default_query_dialog_language">"言語: "</string> <string name="default_query_dialog_language">"言語: "</string>
<string name="default_query_dialog_title">デフォルトキーワード設定</string> <string name="default_query_dialog_title">デフォルトキーワード設定</string>
<string name="main_open_navigation_drawer">メニューを開く</string>
<string name="main_drawer_group_contact_title">お問い合わせ先</string> <string name="main_drawer_group_contact_title">お問い合わせ先</string>
<string name="main_drawer_group_contact_homepage">ホームページ</string> <string name="main_drawer_group_contact_homepage">ホームページ</string>
<string name="main_drawer_group_contact_help">ヘルプ</string> <string name="main_drawer_group_contact_help">ヘルプ</string>
@@ -159,4 +160,5 @@
<string name="unaccessible_download_folder">アンドロイド11以上では外部からのアプリ内部空間接近が不可能です。ダウンロードフォルダを変更しますか</string> <string name="unaccessible_download_folder">アンドロイド11以上では外部からのアプリ内部空間接近が不可能です。ダウンロードフォルダを変更しますか</string>
<string name="settings_networking">ネットワーク</string> <string name="settings_networking">ネットワーク</string>
<string name="settings_recover_downloads">ダウンロードデータベースを再構築</string> <string name="settings_recover_downloads">ダウンロードデータベースを再構築</string>
<string name="main_close_navigation_drawer">メニューを閉じる</string>
</resources> </resources>

View File

@@ -36,6 +36,7 @@
<string name="main_drawer_group_contact_github">Github</string> <string name="main_drawer_group_contact_github">Github</string>
<string name="main_drawer_group_contact_help">도움말</string> <string name="main_drawer_group_contact_help">도움말</string>
<string name="main_drawer_group_contact_homepage">홈페이지</string> <string name="main_drawer_group_contact_homepage">홈페이지</string>
<string name="main_open_navigation_drawer">메뉴 열기</string>
<string name="main_drawer_group_contact_title">문의</string> <string name="main_drawer_group_contact_title">문의</string>
<string name="reader_fab_fullscreen">전체 화면</string> <string name="reader_fab_fullscreen">전체 화면</string>
<string name="channel_download">다운로드</string> <string name="channel_download">다운로드</string>
@@ -159,4 +160,5 @@
<string name="unaccessible_download_folder">안드로이드 11 이상에서는 외부에서 현재 다운로드 폴더에 접근할 수 없습니다. 변경하시겠습니까?</string> <string name="unaccessible_download_folder">안드로이드 11 이상에서는 외부에서 현재 다운로드 폴더에 접근할 수 없습니다. 변경하시겠습니까?</string>
<string name="settings_networking">네트워크</string> <string name="settings_networking">네트워크</string>
<string name="settings_recover_downloads">다운로드 데이터베이스 복구</string> <string name="settings_recover_downloads">다운로드 데이터베이스 복구</string>
<string name="main_close_navigation_drawer">메뉴 닫기</string>
</resources> </resources>

View File

@@ -57,6 +57,8 @@
<string name="main_destination_history">History</string> <string name="main_destination_history">History</string>
<string name="main_destination_downloads">Downloads</string> <string name="main_destination_downloads">Downloads</string>
<string name="main_destination_favorites">Favorites</string> <string name="main_destination_favorites">Favorites</string>
<string name="main_open_navigation_drawer">Open Navigation Drawer</string>
<string name="main_close_navigation_drawer">Close Navigation Drawer</string>
<string name="main_drawer_group_contact_title">Contact</string> <string name="main_drawer_group_contact_title">Contact</string>
<string name="main_drawer_group_contact_help">Help</string> <string name="main_drawer_group_contact_help">Help</string>
<string name="main_drawer_group_contact_homepage">Visit homepage</string> <string name="main_drawer_group_contact_homepage">Visit homepage</string>