Skip to content

Commit da5e98d

Browse files
authored
Merge pull request #1625 from DimensionDev/feature/desktop_app_log
add app logging for desktop
2 parents ee20315 + f0317d4 commit da5e98d

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed

desktopApp/src/main/kotlin/dev/dimension/flare/ui/route/Route.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ internal sealed interface Route {
5151

5252
data object ServiceSelect : ScreenRoute
5353

54+
data object AppLogging : ScreenRoute
55+
5456
data class AllLists(
5557
val accountType: AccountType,
5658
) : ScreenRoute

desktopApp/src/main/kotlin/dev/dimension/flare/ui/route/Router.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import dev.dimension.flare.ui.screen.rss.EditRssSourceScreen
4848
import dev.dimension.flare.ui.screen.rss.ImportOPMLScreen
4949
import dev.dimension.flare.ui.screen.rss.RssListScreen
5050
import dev.dimension.flare.ui.screen.serviceselect.ServiceSelectScreen
51+
import dev.dimension.flare.ui.screen.settings.AppLoggingScreen
5152
import dev.dimension.flare.ui.screen.settings.LocalCacheScreen
5253
import dev.dimension.flare.ui.screen.settings.SettingsScreen
5354
import dev.dimension.flare.ui.screen.settings.WebViewLoginScreen
@@ -400,9 +401,16 @@ internal fun WindowScope.RouteContent(
400401
toLocalCache = {
401402
navigate(Route.LocalCache)
402403
},
404+
toAppLog = {
405+
navigate(Route.AppLogging)
406+
},
403407
)
404408
}
405409

410+
Route.AppLogging -> {
411+
AppLoggingScreen()
412+
}
413+
406414
is Timeline -> {
407415
TimelineScreen(
408416
route.tabItem,
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package dev.dimension.flare.ui.screen.settings
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Row
5+
import androidx.compose.foundation.layout.Spacer
6+
import androidx.compose.foundation.layout.height
7+
import androidx.compose.foundation.layout.padding
8+
import androidx.compose.foundation.lazy.LazyColumn
9+
import androidx.compose.foundation.lazy.items
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.runtime.getValue
12+
import androidx.compose.runtime.mutableStateOf
13+
import androidx.compose.runtime.remember
14+
import androidx.compose.runtime.setValue
15+
import androidx.compose.ui.Alignment
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.unit.dp
18+
import compose.icons.FontAwesomeIcons
19+
import compose.icons.fontawesomeicons.Solid
20+
import compose.icons.fontawesomeicons.solid.FloppyDisk
21+
import compose.icons.fontawesomeicons.solid.Trash
22+
import dev.dimension.flare.LocalWindowPadding
23+
import dev.dimension.flare.Res
24+
import dev.dimension.flare.settings_app_logging_clear
25+
import dev.dimension.flare.settings_app_logging_enable_network_logging
26+
import dev.dimension.flare.settings_app_logging_save
27+
import dev.dimension.flare.ui.component.FAIcon
28+
import dev.dimension.flare.ui.presenter.invoke
29+
import dev.dimension.flare.ui.presenter.settings.DevModePresenter
30+
import dev.dimension.flare.ui.theme.LocalComposeWindow
31+
import dev.dimension.flare.ui.theme.screenHorizontalPadding
32+
import io.github.composefluent.component.AccentButton
33+
import io.github.composefluent.component.Expander
34+
import io.github.composefluent.component.ExpanderItem
35+
import io.github.composefluent.component.SubtleButton
36+
import io.github.composefluent.component.Switcher
37+
import io.github.composefluent.component.Text
38+
import moe.tlaster.precompose.molecule.producePresenter
39+
import org.jetbrains.compose.resources.stringResource
40+
import java.awt.FileDialog
41+
import java.io.File
42+
import kotlin.time.Clock
43+
import kotlin.time.ExperimentalTime
44+
45+
@OptIn(ExperimentalTime::class)
46+
@Composable
47+
internal fun AppLoggingScreen() {
48+
val window = LocalComposeWindow.current
49+
val state by producePresenter { presenter() }
50+
LazyColumn(
51+
modifier =
52+
Modifier
53+
.padding(horizontal = screenHorizontalPadding),
54+
verticalArrangement = Arrangement.spacedBy(2.dp),
55+
contentPadding = LocalWindowPadding.current,
56+
) {
57+
item {
58+
Row(
59+
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End),
60+
modifier = Modifier.fillParentMaxWidth(),
61+
) {
62+
SubtleButton(
63+
onClick = {
64+
FileDialog(window).apply {
65+
mode = FileDialog.SAVE
66+
file = "flare-log-${Clock.System.now().toEpochMilliseconds()}.txt"
67+
isVisible = true
68+
val dir = directory
69+
val file = file
70+
if (dir != null && file != null) {
71+
val data = state.printMessageToString()
72+
val file = File(dir, file)
73+
file.writeText(data)
74+
}
75+
}
76+
},
77+
) {
78+
FAIcon(
79+
FontAwesomeIcons.Solid.FloppyDisk,
80+
contentDescription = stringResource(Res.string.settings_app_logging_save),
81+
)
82+
Text(
83+
stringResource(Res.string.settings_app_logging_save),
84+
)
85+
}
86+
AccentButton(
87+
onClick = {
88+
state.clear()
89+
},
90+
) {
91+
FAIcon(
92+
imageVector = FontAwesomeIcons.Solid.Trash,
93+
contentDescription = stringResource(Res.string.settings_app_logging_clear),
94+
)
95+
Text(
96+
text = stringResource(Res.string.settings_app_logging_clear),
97+
)
98+
}
99+
}
100+
}
101+
item {
102+
Spacer(modifier = Modifier.height(6.dp))
103+
}
104+
item {
105+
ExpanderItem(
106+
heading = {
107+
Text(stringResource(Res.string.settings_app_logging_enable_network_logging))
108+
},
109+
trailing = {
110+
Switcher(
111+
checked = state.enabled,
112+
onCheckStateChange = {
113+
state.setEnabled(it)
114+
},
115+
textBefore = true,
116+
)
117+
},
118+
)
119+
}
120+
item {
121+
Spacer(modifier = Modifier.height(12.dp))
122+
}
123+
items(state.messages) { it ->
124+
var isExpanded by remember { mutableStateOf(false) }
125+
Expander(
126+
expanded = isExpanded,
127+
onExpandedChanged = {
128+
isExpanded = it
129+
},
130+
heading = {
131+
Text(it, maxLines = 3)
132+
},
133+
expandContent = {
134+
Text(
135+
it,
136+
modifier = Modifier.padding(16.dp),
137+
)
138+
},
139+
)
140+
}
141+
}
142+
}
143+
144+
@Composable
145+
private fun presenter() =
146+
run {
147+
remember { DevModePresenter() }.invoke()
148+
}

desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/settings/SettingsScreen.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ import dev.dimension.flare.settings_local_history_title
114114
import dev.dimension.flare.settings_privacy_policy
115115
import dev.dimension.flare.settings_status_appearance_subtitle
116116
import dev.dimension.flare.settings_status_appearance_title
117+
import dev.dimension.flare.settings_storage_app_log
118+
import dev.dimension.flare.settings_storage_app_log_description
117119
import dev.dimension.flare.settings_storage_clear_database
118120
import dev.dimension.flare.settings_storage_clear_database_description
119121
import dev.dimension.flare.settings_storage_clear_image_cache
@@ -172,6 +174,7 @@ import java.util.Locale
172174
internal fun SettingsScreen(
173175
toLogin: () -> Unit,
174176
toLocalCache: () -> Unit,
177+
toAppLog: () -> Unit,
175178
) {
176179
val state by producePresenter { presenter() }
177180

@@ -708,6 +711,23 @@ internal fun SettingsScreen(
708711
},
709712
icon = null,
710713
) {
714+
CardExpanderItem(
715+
onClick = toAppLog,
716+
heading = {
717+
Text(stringResource(Res.string.settings_storage_app_log))
718+
},
719+
caption = {
720+
Text(stringResource(Res.string.settings_storage_app_log_description))
721+
},
722+
trailing = {
723+
FAIcon(
724+
imageVector = FontAwesomeIcons.Solid.AngleRight,
725+
contentDescription = null,
726+
modifier = Modifier.size(12.dp),
727+
)
728+
},
729+
)
730+
711731
ExpanderItem(
712732
heading = {
713733
Text(text = stringResource(Res.string.settings_storage_clear_image_cache))

0 commit comments

Comments
 (0)