|
1 | 1 | package io.github.aecsocket.wordbase |
2 | 2 |
|
3 | 3 | import androidx.activity.compose.BackHandler |
| 4 | +import androidx.compose.foundation.layout.Box |
| 5 | +import androidx.compose.foundation.layout.BoxScope |
4 | 6 | import androidx.compose.foundation.layout.WindowInsets |
5 | 7 | import androidx.compose.foundation.layout.fillMaxSize |
| 8 | +import androidx.compose.foundation.layout.padding |
6 | 9 | import androidx.compose.material3.MaterialTheme |
| 10 | +import androidx.compose.material3.Text |
7 | 11 | import androidx.compose.material3.contentColorFor |
8 | 12 | import androidx.compose.runtime.Composable |
9 | 13 | import androidx.compose.runtime.LaunchedEffect |
10 | 14 | import androidx.compose.runtime.getValue |
11 | 15 | import androidx.compose.runtime.mutableStateOf |
12 | 16 | import androidx.compose.runtime.remember |
13 | 17 | import androidx.compose.runtime.setValue |
| 18 | +import androidx.compose.ui.Alignment |
14 | 19 | import androidx.compose.ui.Modifier |
15 | 20 | import androidx.compose.ui.graphics.Color |
16 | 21 | import androidx.compose.ui.platform.LocalContext |
17 | 22 | import androidx.compose.ui.platform.LocalDensity |
18 | 23 | import androidx.compose.ui.platform.LocalLayoutDirection |
| 24 | +import androidx.compose.ui.res.stringResource |
| 25 | +import androidx.compose.ui.text.style.TextAlign |
| 26 | +import androidx.compose.ui.unit.dp |
19 | 27 | import com.kevinnzou.web.WebView |
20 | 28 | import com.kevinnzou.web.rememberWebViewNavigator |
21 | 29 | import com.kevinnzou.web.rememberWebViewStateWithHTMLData |
22 | 30 | import uniffi.wordbase.Wordbase |
| 31 | +import uniffi.wordbase_api.ProfileId |
23 | 32 | import uniffi.wordbase_api.RecordKind |
24 | 33 | import uniffi.wordbase_api.RecordLookup |
25 | 34 |
|
26 | 35 | @Composable |
27 | | -fun LookupView( |
| 36 | +fun rememberRecordLookup( |
28 | 37 | wordbase: Wordbase, |
| 38 | + profileId: ProfileId, |
29 | 39 | sentence: String, |
30 | 40 | cursor: ULong, |
31 | | - insets: WindowInsets, |
| 41 | +): List<RecordLookup> { |
| 42 | + var records by remember { mutableStateOf(listOf<RecordLookup>()) } |
| 43 | + |
| 44 | + val app = LocalContext.current.app() |
| 45 | + LaunchedEffect(arrayOf(profileId, sentence, cursor, app.dictionaries, app.profiles)) { |
| 46 | + records = wordbase.lookup( |
| 47 | + profileId = profileId, |
| 48 | + sentence = sentence, |
| 49 | + cursor = cursor, |
| 50 | + recordKinds = RecordKind.entries, |
| 51 | + ) |
| 52 | + } |
| 53 | + |
| 54 | + return records |
| 55 | +} |
| 56 | + |
| 57 | +@Composable |
| 58 | +fun RecordsView( |
| 59 | + wordbase: Wordbase, |
| 60 | + records: List<RecordLookup>, |
| 61 | + insets: WindowInsets = WindowInsets(0.dp), |
32 | 62 | containerColor: Color = MaterialTheme.colorScheme.surface, |
33 | 63 | contentColor: Color = contentColorFor(containerColor), |
34 | | - onRecords: (List<RecordLookup>) -> Unit = {}, |
35 | 64 | onExit: (() -> Unit)? = null, |
36 | 65 | ) { |
37 | | - var html by remember { mutableStateOf<String?>(null) } |
38 | | - |
39 | 66 | // amazingly, this scales perfectly |
40 | 67 | val density = LocalDensity.current |
41 | 68 | val layoutDir = LocalLayoutDirection.current |
@@ -64,42 +91,62 @@ fun LookupView( |
64 | 91 | } |
65 | 92 | """.trimIndent() |
66 | 93 | } |
| 94 | + val html = wordbase.renderToHtml(records) + "<style>$extraCss</style>" |
67 | 95 |
|
68 | | - val app = LocalContext.current.app() |
69 | | - LaunchedEffect(arrayOf(sentence, cursor, app.dictionaries, app.profiles)) { |
70 | | - val records = wordbase.lookup( |
71 | | - profileId = 1L, |
72 | | - sentence = sentence, |
73 | | - cursor = cursor, |
74 | | - recordKinds = RecordKind.entries, |
75 | | - ) |
76 | | - onRecords(records) |
77 | | - html = wordbase.renderToHtml(records) + "<style>$extraCss</style>" |
| 96 | + val webViewState = rememberWebViewStateWithHTMLData(html) |
| 97 | + val navigator = rememberWebViewNavigator() |
| 98 | + WebView( |
| 99 | + state = webViewState, |
| 100 | + navigator = navigator, |
| 101 | + modifier = Modifier.fillMaxSize(), |
| 102 | + captureBackPresses = false, |
| 103 | + onCreated = { |
| 104 | + it.settings.javaScriptEnabled = true |
| 105 | + it.settings.allowFileAccess = false |
| 106 | + it.settings.allowContentAccess = false |
| 107 | + } |
| 108 | + ) |
| 109 | + |
| 110 | + BackHandler { |
| 111 | + if (navigator.canGoBack) { |
| 112 | + navigator.navigateBack() |
| 113 | + } else { |
| 114 | + onExit?.invoke() |
| 115 | + } |
78 | 116 | } |
| 117 | +} |
79 | 118 |
|
80 | | - html?.let { html -> |
81 | | - val webViewState = rememberWebViewStateWithHTMLData(html) |
82 | | - val navigator = rememberWebViewNavigator() |
83 | | - WebView( |
84 | | - state = webViewState, |
85 | | - navigator = navigator, |
86 | | - modifier = Modifier.fillMaxSize(), |
87 | | - captureBackPresses = false, |
88 | | - onCreated = { |
89 | | - it.settings.javaScriptEnabled = true |
90 | | - it.settings.allowFileAccess = false |
91 | | - it.settings.allowContentAccess = false |
92 | | - } |
| 119 | +@Composable |
| 120 | +fun NoRecordsView() { |
| 121 | + StatusPage { |
| 122 | + StatusPageTitle( |
| 123 | + text = stringResource(R.string.records_empty), |
93 | 124 | ) |
94 | | - |
95 | | - BackHandler { |
96 | | - if (navigator.canGoBack) { |
97 | | - navigator.navigateBack() |
98 | | - } else { |
99 | | - onExit?.invoke() |
100 | | - } |
101 | | - } |
102 | 125 | } |
103 | 126 | } |
104 | 127 |
|
| 128 | +@Composable |
| 129 | +fun StatusPage(content: @Composable BoxScope.() -> Unit) { |
| 130 | + Box( |
| 131 | + modifier = Modifier |
| 132 | + .fillMaxSize() |
| 133 | + .padding( |
| 134 | + horizontal = 64.dp, |
| 135 | + vertical = 96.dp, |
| 136 | + ), |
| 137 | + contentAlignment = Alignment.Center, |
| 138 | + content = content, |
| 139 | + ) |
| 140 | +} |
| 141 | + |
| 142 | +@Composable |
| 143 | +fun StatusPageTitle(text: String) { |
| 144 | + Text( |
| 145 | + text = text, |
| 146 | + style = MaterialTheme.typography.headlineLarge, |
| 147 | + color = MaterialTheme.colorScheme.onSurfaceVariant, |
| 148 | + textAlign = TextAlign.Center, |
| 149 | + ) |
| 150 | +} |
| 151 | + |
105 | 152 | fun Color.css() = "rgb(${red * 100}% ${green * 100}% ${blue * 100}%)" |
0 commit comments