Skip to content

Commit ce99939

Browse files
committedSep 24, 2019
Addressing previous JetNews comments
Main changes: * Move composables, Icons and app status to different files * Variables renamed Change-Id: I9b9d8fc5a9db36dd83ae87013870eac9aad5a5b0
1 parent cfc9d58 commit ce99939

17 files changed

+292
-232
lines changed
 

Diff for: ‎JetNews/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#JetNews sample
1+
#Jetnews sample
22

33
### License
44

Diff for: ‎JetNews/app/build.gradle

+1-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
1818

1919
apply plugin: 'com.android.application'
2020
apply plugin: 'kotlin-android'
21-
apply plugin: 'kotlin-android-extensions'
2221

2322
Configuration kotlinPluginConfiguration = configurations.create("kotlinPlugin")
2423
tasks.withType(KotlinCompile).configureEach { compile ->
@@ -78,16 +77,10 @@ dependencies {
7877
implementation ('androidx.ui:ui-material:0.1.0-SNAPSHOT')
7978
implementation ('androidx.ui:ui-android-view:0.1.0-SNAPSHOT')
8079
implementation ('androidx.ui:ui-platform:0.1.0-SNAPSHOT')
81-
implementation ('androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0')
8280
implementation ('androidx.appcompat:appcompat:1.1.0-beta01')
8381
implementation ('androidx.activity:activity-ktx:1.0.0-beta01')
84-
implementation ('androidx.lifecycle:lifecycle-extensions:2.0.0')
8582

86-
implementation "androidx.core:core-ktx:1.0.2"
87-
implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0-beta01"
88-
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0-beta01"
89-
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0-beta01"
90-
implementation "com.google.code.gson:gson:2.8.5"
83+
implementation "androidx.core:core-ktx:1.1.0"
9184

9285
implementation fileTree(dir: 'libs', include: ['*.aar'])
9386
implementation "androidx.ui:ui-tooling:+"

Diff for: ‎JetNews/app/src/main/AndroidManifest.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
android:label="@string/app_name"
2525
android:roundIcon="@mipmap/ic_launcher_round"
2626
android:supportsRtl="true"
27-
android:theme="@style/AppTheme">
27+
android:theme="@style/Theme.Jetnews">
2828
<activity android:name=".ui.MainActivity">
2929
<intent-filter>
3030
<action android:name="android.intent.action.MAIN"/>

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/HomeScreen.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fun HomeScreen(icons: Icons, openDrawer: () -> Unit) {
5353
FlexColumn {
5454
inflexible {
5555
TopAppBar<Any>(
56-
{ Text("JetNews") },
56+
{ Text("Jetnews") },
5757
navigationIcon = navigationIcon
5858
)
5959
}
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2019 Google, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.jetnews.ui
18+
19+
import android.content.res.Resources
20+
import androidx.ui.graphics.imageFromResource
21+
import com.example.jetnews.R
22+
import kotlin.LazyThreadSafetyMode.NONE
23+
24+
/**
25+
* Defining and loading here all the images that we use from resources.
26+
*/
27+
class Icons(resources: Resources) {
28+
val appLogo by lazy(NONE) { imageFromResource(resources, R.drawable.jp_news_logo) }
29+
val home by lazy(NONE) { imageFromResource(resources, R.drawable.baseline_home_black_24dp) }
30+
val menu by lazy(NONE) { imageFromResource(resources, R.drawable.baseline_menu_white_24dp) }
31+
val more by lazy(NONE) {
32+
imageFromResource(resources, R.drawable.baseline_more_vert_black_24dp)
33+
}
34+
val back by lazy(NONE) {
35+
imageFromResource(resources, R.drawable.baseline_arrow_back_white_24dp)
36+
}
37+
val bookmarkOn by lazy(NONE) {
38+
imageFromResource(resources, R.drawable.baseline_bookmark_black_24dp)
39+
}
40+
val bookmarkOff by lazy(NONE) {
41+
imageFromResource(resources, R.drawable.baseline_bookmark_border_black_24dp)
42+
}
43+
val heartOn by lazy(NONE) {
44+
imageFromResource(resources, R.drawable.baseline_favorite_black_24dp)
45+
}
46+
val heartOff by lazy(NONE) {
47+
imageFromResource(resources, R.drawable.baseline_favorite_border_black_24dp)
48+
}
49+
val share by lazy(NONE) { imageFromResource(resources, R.drawable.baseline_share_black_24dp) }
50+
val placeholder_1_1 by lazy(NONE) { imageFromResource(resources, R.drawable.placeholder_1_1) }
51+
val placeholder_4_3 by lazy(NONE) { imageFromResource(resources, R.drawable.placeholder_4_3) }
52+
}

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/ImageUtils.kt

+8-8
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,19 @@ fun ZoomedClippedImage(image: Image) {
4848
val drawHeight = imWidth / pAspectRatio
4949
val drawWidth = imWidth
5050
Rect(
51-
top = imHeight / 2 - drawHeight / 2,
52-
left = imWidth / 2 - drawWidth / 2,
53-
right = imWidth / 2 + drawWidth / 2,
54-
bottom = imHeight / 2 + drawHeight / 2
51+
top = (imHeight - drawHeight) / 2,
52+
left = (imWidth - drawWidth) / 2,
53+
right = (imWidth + drawWidth) / 2,
54+
bottom = (imHeight + drawHeight) / 2
5555
)
5656
} else {
5757
val drawHeight = imHeight
5858
val drawWidth = imHeight * pAspectRatio
5959
Rect(
60-
top = imHeight / 2 - drawHeight / 2,
61-
left = imWidth / 2 - drawWidth / 2,
62-
right = imWidth / 2 + drawWidth / 2,
63-
bottom = imHeight / 2 + drawHeight / 2
60+
top = (imHeight - drawHeight) / 2,
61+
left = (imWidth - drawWidth) / 2,
62+
right = (imWidth + drawWidth) / 2,
63+
bottom = (imHeight + drawHeight) / 2
6464
)
6565
}
6666

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2019 Google, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.jetnews.ui
18+
19+
import androidx.compose.Composable
20+
import androidx.compose.composer
21+
import androidx.compose.frames.open
22+
import androidx.compose.state
23+
import androidx.compose.unaryPlus
24+
import androidx.ui.core.Text
25+
import androidx.ui.core.dp
26+
import androidx.ui.layout.Column
27+
import androidx.ui.layout.CrossAxisAlignment
28+
import androidx.ui.layout.HeightSpacer
29+
import androidx.ui.layout.LayoutSize
30+
import androidx.ui.layout.MainAxisAlignment
31+
import androidx.ui.layout.Padding
32+
import androidx.ui.layout.Row
33+
import androidx.ui.material.Button
34+
import androidx.ui.material.DrawerState
35+
import androidx.ui.material.MaterialTheme
36+
import androidx.ui.material.ModalDrawerLayout
37+
import androidx.ui.material.TextButtonStyle
38+
39+
@Composable
40+
fun JetnewsApp(icons: Icons) {
41+
42+
val (drawerState, onDrawerStateChange) = +state { DrawerState.Closed }
43+
44+
MaterialTheme(
45+
colors = lightThemeColors,
46+
typography = typography
47+
) {
48+
ModalDrawerLayout(
49+
drawerState = drawerState,
50+
onStateChange = onDrawerStateChange,
51+
drawerContent = { AppDrawer(closeDrawer = { onDrawerStateChange(DrawerState.Closed) }) },
52+
bodyContent = {
53+
AppContent(
54+
icons = icons,
55+
openDrawer = { onDrawerStateChange(DrawerState.Opened) })
56+
}
57+
)
58+
}
59+
}
60+
61+
@Composable
62+
private fun DrawerButton(drawerButtonText: String, action: () -> Unit) {
63+
Button(onClick = { action() }, style = TextButtonStyle()) {
64+
Row(
65+
mainAxisAlignment = MainAxisAlignment.Start,
66+
mainAxisSize = LayoutSize.Expand
67+
) {
68+
Text(drawerButtonText)
69+
}
70+
}
71+
}
72+
73+
@Composable
74+
private fun AppContent(icons: Icons, openDrawer: () -> Unit) {
75+
val screen = JetnewsStatus.currentScreen
76+
when (screen) {
77+
is Screen.Home -> HomeScreen(icons = icons, openDrawer = { openDrawer() })
78+
is Screen.Interests -> TopicsScreen(icons = icons, openDrawer = { openDrawer() })
79+
is Screen.Article -> ArticleScreen(icons = icons, postId = screen.postId)
80+
}
81+
}
82+
83+
@Composable
84+
private fun AppDrawer(closeDrawer: () -> Unit) {
85+
Column(
86+
crossAxisAlignment = CrossAxisAlignment.Start,
87+
crossAxisSize = LayoutSize.Expand,
88+
mainAxisAlignment = MainAxisAlignment.Start,
89+
mainAxisSize = LayoutSize.Expand
90+
) {
91+
HeightSpacer(40.dp)
92+
Padding(8.dp) {
93+
DrawerButton("Home") {
94+
navigateTo(Screen.Home)
95+
closeDrawer()
96+
}
97+
}
98+
99+
Padding(8.dp) {
100+
DrawerButton("Interests") {
101+
navigateTo(Screen.Interests)
102+
closeDrawer()
103+
}
104+
}
105+
}
106+
}

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt

+1-145
Original file line numberDiff line numberDiff line change
@@ -16,84 +16,10 @@
1616

1717
package com.example.jetnews.ui
1818

19-
import android.content.res.Resources
2019
import android.os.Bundle
2120
import androidx.appcompat.app.AppCompatActivity
22-
import androidx.compose.Composable
23-
import androidx.compose.Model
2421
import androidx.compose.composer
25-
import androidx.compose.state
26-
import androidx.compose.unaryPlus
27-
import androidx.ui.core.Text
28-
import androidx.ui.core.dp
2922
import androidx.ui.core.setContent
30-
import androidx.ui.graphics.imageFromResource
31-
import androidx.ui.layout.Column
32-
import androidx.ui.layout.CrossAxisAlignment
33-
import androidx.ui.layout.HeightSpacer
34-
import androidx.ui.layout.LayoutSize
35-
import androidx.ui.layout.MainAxisAlignment
36-
import androidx.ui.layout.Padding
37-
import androidx.ui.layout.Row
38-
import androidx.ui.material.Button
39-
import androidx.ui.material.DrawerState
40-
import androidx.ui.material.MaterialTheme
41-
import androidx.ui.material.ModalDrawerLayout
42-
import androidx.ui.material.TextButtonStyle
43-
import com.example.jetnews.R
44-
45-
class Icons(resources: Resources) {
46-
val appLogo by lazy { imageFromResource(resources, R.drawable.jp_news_logo) }
47-
val home by lazy { imageFromResource(resources, R.drawable.baseline_home_black_24dp) }
48-
val menu by lazy { imageFromResource(resources, R.drawable.baseline_menu_white_24dp) }
49-
val more by lazy { imageFromResource(resources, R.drawable.baseline_more_vert_black_24dp) }
50-
val back by lazy { imageFromResource(resources, R.drawable.baseline_arrow_back_white_24dp) }
51-
val bookmarkOn by lazy { imageFromResource(resources, R.drawable.baseline_bookmark_black_24dp) }
52-
val bookmarkOff by lazy {
53-
imageFromResource(
54-
resources,
55-
R.drawable.baseline_bookmark_border_black_24dp
56-
)
57-
}
58-
val heartOn by lazy { imageFromResource(resources, R.drawable.baseline_favorite_black_24dp) }
59-
val heartOff by lazy {
60-
imageFromResource(
61-
resources,
62-
R.drawable.baseline_favorite_border_black_24dp
63-
)
64-
}
65-
val share by lazy { imageFromResource(resources, R.drawable.baseline_share_black_24dp) }
66-
val placeholder_1_1 by lazy { imageFromResource(resources, R.drawable.placeholder_1_1) }
67-
val placeholder_4_3 by lazy { imageFromResource(resources, R.drawable.placeholder_4_3) }
68-
}
69-
70-
sealed class Screen {
71-
object Home : Screen()
72-
data class Article(val postId: String) : Screen()
73-
object Interests : Screen()
74-
}
75-
76-
@Model
77-
class JetNewsStatus {
78-
var shownScreen: Screen = Screen.Home
79-
var favorites = setOf<String>()
80-
}
81-
82-
val jetNewsStatus = JetNewsStatus()
83-
84-
fun navigateTo(destination: Screen) {
85-
jetNewsStatus.shownScreen = destination
86-
}
87-
88-
fun toggleBookmark(postId: String) {
89-
with(jetNewsStatus) {
90-
favorites = if (favorites.contains(postId)) {
91-
favorites - postId
92-
} else {
93-
favorites + postId
94-
}
95-
}
96-
}
9723

9824
class MainActivity : AppCompatActivity() {
9925

@@ -102,77 +28,7 @@ class MainActivity : AppCompatActivity() {
10228
val icons = Icons(resources)
10329
posts = getPostsWithImagesLoaded(posts, resources)
10430
setContent {
105-
JetNewsApp(icons)
31+
JetnewsApp(icons)
10632
}
10733
}
10834
}
109-
110-
@Composable
111-
fun JetNewsApp(icons: Icons) {
112-
113-
val (drawerState, onDrawerStateChange) = +state { DrawerState.Closed }
114-
115-
fun openDrawer() {
116-
onDrawerStateChange(DrawerState.Opened)
117-
}
118-
119-
fun closeDrawer() {
120-
onDrawerStateChange(DrawerState.Closed)
121-
}
122-
123-
@Composable
124-
fun AppContent() {
125-
val screen = jetNewsStatus.shownScreen
126-
when (screen) {
127-
is Screen.Home -> HomeScreen(icons = icons, openDrawer = { openDrawer() })
128-
is Screen.Interests -> TopicsScreen(icons = icons, openDrawer = { openDrawer() })
129-
is Screen.Article -> ArticleScreen(icons = icons, postId = screen.postId)
130-
}
131-
}
132-
133-
@Composable
134-
fun AppDrawer() {
135-
@Composable
136-
fun DrawerButton(text: String, destination: Screen) {
137-
Button(onClick = {
138-
navigateTo(destination)
139-
closeDrawer()
140-
}, style = TextButtonStyle()) {
141-
Row(
142-
mainAxisAlignment = MainAxisAlignment.Start,
143-
mainAxisSize = LayoutSize.Expand
144-
) {
145-
Text(text)
146-
}
147-
}
148-
}
149-
150-
Column(
151-
crossAxisAlignment = CrossAxisAlignment.Start,
152-
crossAxisSize = LayoutSize.Expand,
153-
mainAxisAlignment = MainAxisAlignment.Start,
154-
mainAxisSize = LayoutSize.Expand
155-
) {
156-
HeightSpacer(40.dp)
157-
Padding(8.dp) {
158-
DrawerButton("Home", Screen.Home)
159-
}
160-
161-
Padding(8.dp) {
162-
DrawerButton("Interests", Screen.Interests)
163-
}
164-
}
165-
}
166-
167-
MaterialTheme(
168-
colors = lightThemeColors,
169-
typography = typography
170-
) {
171-
ModalDrawerLayout(
172-
drawerState = drawerState,
173-
onStateChange = onDrawerStateChange,
174-
drawerContent = { AppDrawer() },
175-
bodyContent = { AppContent() }
176-
)
177-
}
178-
}

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/PostCardTop.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ fun PostCardTop(post: Post) {
5555
}
5656
HeightSpacer(16.dp)
5757
Opacity(0.87f) {
58-
Text(post.title, style = +themeTextStyle { h6 })
58+
Text(text = post.title, style = +themeTextStyle { h6 })
5959
}
6060
Opacity(0.87f) {
61-
Text(post.metadata.author.name, style = +themeTextStyle { body2 })
61+
Text(text = post.metadata.author.name, style = +themeTextStyle { body2 })
6262
}
6363
Opacity(0.6f) {
64-
Text("${post.metadata.date} - ${post.metadata.readTimeMinutes} min read",
64+
Text(text = "${post.metadata.date} - ${post.metadata.readTimeMinutes} min read",
6565
style = +themeTextStyle { body2 })
6666
}
6767
}

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/PostCardYourNetwork.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,12 @@ fun PostCardPopular(post: Post, icons: Icons) {
6464
}
6565
}
6666
Opacity(0.87f) {
67-
Text(post.metadata.author.name, style = +themeTextStyle { body2 })
67+
Text(
68+
text = post.metadata.author.name,
69+
style = +themeTextStyle { body2 })
6870
}
6971
Opacity(0.6f) {
70-
Text("${post.metadata.date} - ${post.metadata.readTimeMinutes} min read",
72+
Text(text = "${post.metadata.date} - ${post.metadata.readTimeMinutes} min read",
7173
style = +themeTextStyle { body2 })
7274
}
7375
}

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/PostCards.kt

+18-4
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ fun AuthorAndReadTime(post: Post) {
4343
Opacity(0.6f) {
4444
FlexRow {
4545
flexible(1f) {
46-
Text(post.metadata.author.name, style = +themeTextStyle { body2 })
46+
Text(text = post.metadata.author.name, style = +themeTextStyle { body2 })
4747
}
4848
inflexible {
49-
Text(" - ${post.metadata.readTimeMinutes} min read", style = +themeTextStyle { body2 })
49+
Text(
50+
text = " - ${post.metadata.readTimeMinutes} min read",
51+
style = +themeTextStyle { body2 })
5052
}
5153
}
5254
}
@@ -126,7 +128,9 @@ fun PostCardHistory(post: Post, icons: Icons) {
126128
mainAxisSize = LayoutSize.Expand
127129
) {
128130
Opacity(0.38f) {
129-
Text("BASED ON YOUR HISTORY", style = +themeTextStyle { overline })
131+
Text(
132+
text = "BASED ON YOUR HISTORY",
133+
style = +themeTextStyle { overline })
130134
}
131135
PostTitle(post = post)
132136
AuthorAndReadTime(post)
@@ -142,9 +146,19 @@ fun PostCardHistory(post: Post, icons: Icons) {
142146
}
143147
}
144148

149+
fun toggleBookmark(postId: String) {
150+
JetnewsStatus.run {
151+
if (favorites.contains(postId)) {
152+
favorites.remove(postId)
153+
} else {
154+
favorites.add(postId)
155+
}
156+
}
157+
}
158+
145159
@Composable
146160
fun BookmarkButton(post: Post, icons: Icons) {
147-
val bookmarked = jetNewsStatus.favorites.contains(post.id)
161+
val bookmarked = JetnewsStatus.favorites.contains(post.id)
148162
val value = if (bookmarked) ToggleableState.Checked else ToggleableState.Unchecked
149163
Surface {
150164
Ripple(bounded = true) {

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/PostContent.kt

+51-56
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,33 @@ import androidx.ui.text.style.TextDecoration
5050
import androidx.ui.text.style.TextIndent
5151
import com.example.jetnews.R
5252

53+
private const val defaultBodyLineHeight = 1.49f
54+
private val defaultSpacerSize = 16.dp
55+
56+
private val codeFontFamily = FontFamily(font = Font(name = "fira_code_regular.ttf"))
57+
58+
private val italicTextStyle = (+themeTextStyle { body1 }).copy(fontStyle = FontStyle.Italic)
59+
private val boldTextStyle = (+themeTextStyle { body1 }).copy(fontWeight = FontWeight.bold)
60+
private val codeTextStyle = (+themeTextStyle { body1 })
61+
.copy(background = Color.LightGray, fontFamily = codeFontFamily)
62+
private val linkTextStyle = (+themeTextStyle { body1 }).copy(decoration = TextDecoration.Underline)
63+
64+
private val bulletParagraphStyle = ParagraphStyle(textIndent = TextIndent(firstLine = Px(30f)))
65+
private val metadataTextStyle = +themeTextStyle { caption.copy(color = Color.Gray) }
66+
5367
@Composable
5468
fun PostContent(post: Post) {
5569
VerticalScroller {
5670
Padding(left = defaultSpacerSize, right = defaultSpacerSize) {
5771
Column(crossAxisAlignment = CrossAxisAlignment.Start) {
5872
HeightSpacer(height = defaultSpacerSize)
59-
Text(text = post.title, style = titleTextSyle)
73+
Text(text = post.title, style = +themeTextStyle { h4 })
6074
HeightSpacer(height = defaultSpacerSize)
61-
post.subtitle?.let {
75+
post.subtitle?.let { subtitle ->
6276
Text(
63-
text = it,
64-
style = subtitleTextStyle,
65-
paragraphStyle = subtitleParagraphStyle
77+
text = subtitle,
78+
style = +themeTextStyle { subtitle1 },
79+
paragraphStyle = ParagraphStyle(lineHeight = 1.49f)
6680
)
6781
HeightSpacer(height = defaultSpacerSize)
6882
}
@@ -76,12 +90,12 @@ fun PostContent(post: Post) {
7690

7791
@Composable
7892
fun PostMetadata(metadata: Metadata) {
79-
val text =
93+
val postMetadata =
8094
"${metadata.author.name} on ${metadata.date} - ${metadata.readTimeMinutes} min read"
8195
Row {
8296
DefaultAuthorImage()
8397
WidthSpacer(width = 8.dp)
84-
Text(text = text, style = metadataTextStyle)
98+
Text(text = postMetadata, style = metadataTextStyle)
8599
}
86100
}
87101

@@ -100,34 +114,15 @@ fun DefaultAuthorImage() {
100114
@Composable
101115
fun PostContents(paragraphs: List<Paragraph>) {
102116
paragraphs.forEach {
103-
HeightSpacer(height = 4.dp)
104-
Paragraph(paragraph = it)
105-
HeightSpacer(height = 4.dp)
106-
}
107-
}
108-
109-
private fun getTextAndParagraphStyle(paragraph: Paragraph): Pair<TextStyle, ParagraphStyle> {
110-
var textStyle: TextStyle = bodyTextStyle
111-
var paragraphStyle = ParagraphStyle()
112-
113-
when (paragraph.type) {
114-
is ParagraphType.Caption -> textStyle = bodyTextStyle
115-
ParagraphType.Title -> textStyle = h3TextStyle
116-
ParagraphType.Subtitle -> textStyle = subtitleTextStyle
117-
ParagraphType.Text -> {
118-
textStyle = bodyTextStyle
119-
paragraphStyle = paragraphStyle.copy(lineHeight = defaultBodyLineHeight)
117+
Padding(top = 4.dp, bottom = 4.dp) {
118+
Paragraph(paragraph = it)
120119
}
121-
ParagraphType.CodeBlock -> textStyle = codeTextStyle
122-
ParagraphType.Quote -> textStyle = bodyTextStyle
123-
ParagraphType.Bullet -> paragraphStyle = bulletParagraphStyle
124120
}
125-
return Pair(textStyle, paragraphStyle)
126121
}
127122

128123
@Composable
129124
fun Paragraph(paragraph: Paragraph) {
130-
val (textStyle, paragraphStyle) = getTextAndParagraphStyle(paragraph)
125+
val (textStyle, paragraphStyle) = paragraph.type.getTextAndParagraphStyle()
131126

132127
val annotatedString = paragraphToAnnotatedString(paragraph)
133128
when (paragraph.type) {
@@ -170,35 +165,35 @@ fun BulletParagraph(text: AnnotatedString, textStyle: TextStyle, paragraphStyle:
170165
}
171166
}
172167

173-
fun paragraphToAnnotatedString(paragraph: Paragraph): AnnotatedString {
174-
val styles = paragraph.markups.map {
175-
when (it.type) {
176-
is MarkupType.Italic -> AnnotatedString.Item(italicTextStyle, it.start, it.end)
177-
is MarkupType.Link -> AnnotatedString.Item(linkTextStyle, it.start, it.end)
178-
is MarkupType.Bold -> AnnotatedString.Item(boldTextStyle, it.start, it.end)
179-
is MarkupType.Code -> AnnotatedString.Item(codeTextStyle, it.start, it.end)
168+
private fun ParagraphType.getTextAndParagraphStyle(): Pair<TextStyle, ParagraphStyle> {
169+
var textStyle: TextStyle = +themeTextStyle { body1 }
170+
var paragraphStyle = ParagraphStyle()
171+
172+
when (this) {
173+
is ParagraphType.Caption -> textStyle = +themeTextStyle { body1 }
174+
ParagraphType.Title -> textStyle = +themeTextStyle { h4 }
175+
ParagraphType.Subtitle -> textStyle = +themeTextStyle { subtitle1 }
176+
ParagraphType.Text -> {
177+
textStyle = +themeTextStyle { body1 }
178+
paragraphStyle = paragraphStyle.copy(lineHeight = defaultBodyLineHeight)
180179
}
180+
ParagraphType.CodeBlock -> textStyle = codeTextStyle
181+
ParagraphType.Quote -> textStyle = +themeTextStyle { body1 }
182+
ParagraphType.Bullet -> paragraphStyle = bulletParagraphStyle
181183
}
182-
return AnnotatedString(text = paragraph.text, textStyles = styles)
184+
return textStyle to paragraphStyle
183185
}
184186

185-
const val defaultBodyLineHeight = 1.49f
186-
val defaultSpacerSize = 16.dp
187-
188-
val codeFontFamily = FontFamily(font = Font(name = "fira_code_regular.ttf"))
189-
190-
val titleTextSyle = +themeTextStyle { h4 }
191-
192-
val subtitleTextStyle = +themeTextStyle { subtitle1 }
193-
val subtitleParagraphStyle = ParagraphStyle(lineHeight = 1.49f)
194-
val bodyTextStyle = +themeTextStyle { body1 }
195-
val h3TextStyle = +themeTextStyle { h4 }
196-
197-
val italicTextStyle = (+themeTextStyle { body1 }).copy(fontStyle = FontStyle.Italic)
198-
val boldTextStyle = (+themeTextStyle { body1 }).copy(fontWeight = FontWeight.bold)
199-
val codeTextStyle = (+themeTextStyle { body1 })
200-
.copy(background = Color.LightGray, fontFamily = codeFontFamily)
201-
val linkTextStyle = (+themeTextStyle { body1 }).copy(decoration = TextDecoration.Underline)
187+
private fun paragraphToAnnotatedString(paragraph: Paragraph): AnnotatedString {
188+
val styles = paragraph.markups.map { it.toAnnotatedStringItem() }
189+
return AnnotatedString(text = paragraph.text, textStyles = styles)
190+
}
202191

203-
val bulletParagraphStyle = ParagraphStyle(textIndent = TextIndent(firstLine = Px(30f)))
204-
val metadataTextStyle = +themeTextStyle { caption.copy(color = Color.Gray) }
192+
private fun Markup.toAnnotatedStringItem(): AnnotatedString.Item<TextStyle> {
193+
return when (this.type) {
194+
is MarkupType.Italic -> AnnotatedString.Item(italicTextStyle, start, end)
195+
is MarkupType.Link -> AnnotatedString.Item(linkTextStyle, start, end)
196+
is MarkupType.Bold -> AnnotatedString.Item(boldTextStyle, start, end)
197+
is MarkupType.Code -> AnnotatedString.Item(codeTextStyle, start, end)
198+
}
199+
}

Diff for: ‎JetNews/app/src/main/java/com/example/jetnews/ui/PostsData.kt

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ import android.content.res.Resources
2020
import androidx.ui.graphics.imageFromResource
2121
import com.example.jetnews.R
2222

23+
/**
24+
* Define hardcoded posts to avoid handling any non-ui operations.
25+
*/
26+
2327
val pietro = PostAuthor("Pietro Maggi", "https://medium.com/@pmaggi")
2428
val manuel = PostAuthor("Manuel Vivo", "https://medium.com/@manuelvicnt")
2529
val florina = PostAuthor(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2019 Google, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.jetnews.ui
18+
19+
import androidx.compose.Model
20+
21+
/**
22+
* Class defining the screens we have in the app: home, article details and interests
23+
*/
24+
sealed class Screen {
25+
object Home : Screen()
26+
data class Article(val postId: String) : Screen()
27+
object Interests : Screen()
28+
}
29+
30+
@Model
31+
object JetnewsStatus {
32+
var currentScreen: Screen = Screen.Home
33+
var favorites = mutableSetOf<String>()
34+
}
35+
36+
fun navigateTo(destination: Screen) {
37+
JetnewsStatus.currentScreen = destination
38+
}

Diff for: ‎JetNews/app/src/main/res/values/strings.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616
-->
1717

1818
<resources>
19-
<string name="app_name">JetNews</string>
19+
<string name="app_name">Jetnews</string>
2020
</resources>

Diff for: ‎JetNews/app/src/main/res/values/styles.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<!-- Base application theme. In this Jetpack Compose sample app, these colors
2121
don't affect the Composable functions, just the color of the Status Bar.
2222
For the colors used by the Composable functions, see Themes.kt -->
23-
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
23+
<style name="Theme.Jetnews" parent="Theme.AppCompat.Light.NoActionBar">
2424
<item name="colorPrimary">@color/colorPrimary</item>
2525
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
2626
<item name="colorAccent">@color/colorAccent</item>

Diff for: ‎JetNews/gradle/wrapper/gradle-wrapper.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=../../../../androidx-master-dev/tools/external/gradle/gradle-5.5.1-bin.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip

0 commit comments

Comments
 (0)
Please sign in to comment.