diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2b20fed0..b326dbab 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,5 +1,7 @@
import com.google.devtools.ksp.gradle.KspAATask
-import org.jetbrains.compose.desktop.application.dsl.TargetFormat.*
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat.Deb
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat.Dmg
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat.Msi
plugins {
alias(libs.plugins.androidApplication)
@@ -150,8 +152,8 @@ android {
applicationId = "com.daniebeler.pfpixelix"
minSdk = 26
targetSdk = 35
- versionCode = 32
- versionName = "4.1.1"
+ versionCode = 33
+ versionName = "4.2.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
diff --git a/app/src/commonMain/composeResources/values-de-rDE/strings.xml b/app/src/commonMain/composeResources/values-de-rDE/strings.xml
index 3a22ca8a..f4dcd8c8 100644
--- a/app/src/commonMain/composeResources/values-de-rDE/strings.xml
+++ b/app/src/commonMain/composeResources/values-de-rDE/strings.xml
@@ -20,12 +20,12 @@
Follower
- Follower
- - Followers
+ - Follower
Gefolgt
- - Following
- - Following
+ - Gefolgt
+ - Gefolgt
- Beitrag
@@ -264,19 +264,19 @@
- Jahr
- Jahre
- Blur sensitive content
- Autoplay Videos
- Report this post
- Report
+ sensiblen Inhalt unschärfen
+ Videos automatisch abspielen
+ Diesen Beitrag melden
+ Melden
Spam
- Adult or Sensitive Content
- Abusive or Harmful
- Underage Account
- Violence
- Copyright infringement
- Impersonation
- Scam
- Terrorism
- Reported
- Delete Account
+ Erwachsenen oder sensibler Inhalt
+ Missbräuchlich oder Schädigend
+ Minderjährigen-Konto
+ Gewalt
+ Urheberrechtsverletzung
+ Identitätswechsel
+ Betrug
+ Terrorismus
+ Gemeldet
+ Konto löschen
diff --git a/app/src/commonMain/composeResources/values-el-rGR/strings.xml b/app/src/commonMain/composeResources/values-el-rGR/strings.xml
index 6e5c925e..38a3aa84 100644
--- a/app/src/commonMain/composeResources/values-el-rGR/strings.xml
+++ b/app/src/commonMain/composeResources/values-el-rGR/strings.xml
@@ -264,19 +264,19 @@
- έτος
- έτη
- Blur sensitive content
- Autoplay Videos
- Report this post
- Report
- Spam
- Adult or Sensitive Content
- Abusive or Harmful
- Underage Account
- Violence
- Copyright infringement
- Impersonation
- Scam
- Terrorism
- Reported
- Delete Account
+ Θόλωμα ευαίσθητου περιεχομένου
+ Αυτόματη Αναπαραγωγή Βίντεο
+ Αναφορά αυτής της ανάρτησης
+ Αναφορά
+ Σπαμ
+ Ενήλικο ή Ευαίσθητο Περιεχόμενο
+ Καταχρηστικό ή Επιβλαβές
+ Λογαριασμός Ανηλίκου
+ Βία
+ Παραβίαση πνευματικών δικαιωμάτων
+ Πλαστοπροσωπία
+ Απάτη
+ Τρομοκρατία
+ Αναφέρθηκε
+ Διαγραφή Λογαριασμού
diff --git a/app/src/commonMain/composeResources/values-en-rUS/strings.xml b/app/src/commonMain/composeResources/values-en-rUS/strings.xml
index 706fd559..260b83ab 100644
--- a/app/src/commonMain/composeResources/values-en-rUS/strings.xml
+++ b/app/src/commonMain/composeResources/values-en-rUS/strings.xml
@@ -66,7 +66,7 @@
yearly
monthly
daily
- I don’t have a profile
+ I don\'t have a profile
Server URL
Are you sure you want to log out?
Logout?
diff --git a/app/src/commonMain/composeResources/values-fr-rFR/strings.xml b/app/src/commonMain/composeResources/values-fr-rFR/strings.xml
index 02926154..62e41420 100644
--- a/app/src/commonMain/composeResources/values-fr-rFR/strings.xml
+++ b/app/src/commonMain/composeResources/values-fr-rFR/strings.xml
@@ -3,7 +3,7 @@
Notifications
Paramètres
Publications aimées
- Publications favorites
+ Publications sauvegardées
Hashtags suivis
Comptes bloqués
Comptes masqués
@@ -85,13 +85,13 @@
Description du média
Aucune publication pour l’instant
vous a mentionné·e
- Aucune publication favorite
+ Aucune publication sauvegardée
Rien à afficher
Nouvelle publication
Publier
Texte Alternatif
- légende
- Média suggestif/sensible
+ Description
+ Média suggestif ou sensible
avertissement de contenu ou texte caché
Visibilité
non répertorié
@@ -160,10 +160,10 @@
Ne plus masquer le compte ?
Masquer
Masquer le compte ?
- a envoyé un mp
- système
- sombre
- clair
+ a envoyé un message privé
+ Système
+ Sombre
+ Clair
Thème de l\'application
Envoyer le message
Sélectionner un destinataire
@@ -200,7 +200,7 @@
Si une icône autre que celle par défaut est sélectionnée, deux icônes s’afficheront dans votre tiroir d’applications.
Compte Actif :
Autres comptes :
- Ajouter un compte Pixeled
+ Ajouter un compte Pixelfed
Télécharger l’image
Profil
Boîte de réception
@@ -223,7 +223,7 @@
Localisation
Mentions
Explorer
- reblogged by %1$s
+ republié par %1$s
Mode sans distraction
Masque la description, les J’aime et les boutons des messages.
Paramètres de republication
@@ -233,7 +233,7 @@
Lire la suite
En voir moins
Inscrit·e le %1$s
- ago
+
Supprimer le message
Lecteur vidéo non pris en charge
@@ -264,19 +264,19 @@
- année
- années
- Blur sensitive content
- Autoplay Videos
- Report this post
- Report
- Spam
- Adult or Sensitive Content
- Abusive or Harmful
- Underage Account
+ Flouter le contenu sensible
+ Lecture automatique des vidéos
+ Signaler cet publication
+ Signaler
+ Indésirable
+ Contenu pour adulte ou sensible
+ Abusif ou Dangereux
+ Compte Mineur
Violence
- Copyright infringement
- Impersonation
- Scam
- Terrorism
- Reported
- Delete Account
+ Violation de droit d\'auteur
+ Usurpation d\'identité
+ Fraude
+ Terrorisme
+ Signalé
+ Supprimer le compte
diff --git a/app/src/commonMain/composeResources/values-it-rIT/strings.xml b/app/src/commonMain/composeResources/values-it-rIT/strings.xml
index 015bb83c..1ff21ee4 100644
--- a/app/src/commonMain/composeResources/values-it-rIT/strings.xml
+++ b/app/src/commonMain/composeResources/values-it-rIT/strings.xml
@@ -19,17 +19,17 @@
Smetti di seguire
Seguaci
- - Follower
- - Followers
+ - Seguace
+ - Seguaci
Seguiti
- - Following
- - Following
+ - Seguito
+ - Seguiti
- Post
- - Posts
+ - Post
Post
Hashtag
@@ -229,54 +229,54 @@
Impostazioni di ripubblicazione
AMOLED
Ancora nessun seguace
- Not following anyone
- Read More
- Read Less
- Joined %1$s
+ Non stai seguendo nessuno
+ Leggi di più
+ Leggi di meno
+ Unito il %1$s
fa
Elimina messaggio
- Video player is not supported
+ Il riproduttore video non è supportato
- - second
- - seconds
+ - secondo
+ - secondi
- - minute
- - minutes
+ - minuto
+ - minuti
- - hour
- - hours
+ - ora
+ - ore
- - day
- - days
+ - giorno
+ - giorni
- - week
- - weeks
+ - settimana
+ - settimane
- - month
- - months
+ - mese
+ - mesi
- - year
- - years
+ - anno
+ - anni
- Blur sensitive content
- Autoplay Videos
- Report this post
- Report
+ Nascondi contenuto sensibile
+ Riproduci automaticamente i video
+ Segnala questo post
+ Segnala
Spam
- Adult or Sensitive Content
- Abusive or Harmful
- Underage Account
- Violence
- Copyright infringement
- Impersonation
- Scam
- Terrorism
- Reported
- Delete Account
+ Contenuto sensibile o per adulti
+ Dannoso o Abusivo
+ Account Minorenne
+ Violenza
+ Violazione del copyright
+ Impersonificazione
+ Truffa
+ Terrorismo
+ Segnalato
+ Elimina Account
diff --git a/app/src/commonMain/composeResources/values-zh-rTW/strings.xml b/app/src/commonMain/composeResources/values-zh-rTW/strings.xml
index 8ab1324a..c0eebbae 100644
--- a/app/src/commonMain/composeResources/values-zh-rTW/strings.xml
+++ b/app/src/commonMain/composeResources/values-zh-rTW/strings.xml
@@ -1,205 +1,205 @@
- Notifications
- Settings
- Liked Posts
- Bookmarked Posts
- Followed Hashtags
- Blocked Profiles
- Muted Profiles
- Logout
- Open in browser
- Share this profile
- Block this profile
- Unblock this profile
- Mute this profile
- Unmute this profile
- Load More
- Follow
- Unfollow
- Followers
+ 通知
+ 設定
+ 喜歡的貼文
+ 已加書籤的貼文
+ 已追蹤的標籤
+ 已封鎖個人檔案
+ 已靜音個人檔案
+ 登出
+ 以瀏覽器開啟
+ 分享此個人檔案
+ 封鎖此個人檔案
+ 解封此個人檔案
+ 靜音此個人檔案
+ 取消靜音此個人檔案
+ 載入更多
+ 追蹤
+ 取消追蹤
+ 追蹤者
- - Followers
+ - 追蹤者
- Following
+ 追蹤中
- - Following
+ - 追蹤中
- - Posts
+ - 貼文
- Posts
- Hashtags
- reblogged your post
- liked your post
- followed you
- Share this post
- Trending
- Profiles
- Rules
- Instance version
- Terms of use
- Privacy Policy
- Admin
- Users
- Stats
- unblock
- Unblock
- Unblock Profile?
- Confirm to unblock this profile
- no blocked profiles
- Cancel
- Post by
- Liked by
- Delete this post
- Delete post?
- This action cannot be undone
- Delete
- This is the End!
- and
- Followed by
- other
- others
- yearly
- monthly
- daily
- I don\'t have a profile
- Server URL
- Are you sure you want to log out?
- Logout?
- View %1$s comments
- Leave a comment
- No comments yet
- No likes yet
- no liked posts
- Local
- Global
- Home
- %1$s likes
- Search
- Unmute
- unmute
- Media Description
- No posts yet
- mentioned you
- No bookmarked posts
- Nothing to show
- New post
- Publish
- Alt Text
- caption
- Sensitive/NSFW Media
- content warning or spoiler text
- Audience
- unlisted
- followers only
- public
- No followed hashtags
- No muted profiles
- Visibility: %1$s
- Clear cache
- Preferences
- Hide sensitive content
- About %1$s
- More settings
- Use in-app-browser
+ 貼文
+ 標籤
+ 轉發了你的貼文
+ 對你的貼文表示喜歡
+ 已追蹤你
+ 分享這篇貼文
+ 熱門
+ 個人檔案
+ 規則
+ 實例版本
+ 使用條款
+ 隱私政策
+ 管理員
+ 用戶
+ 狀態
+ 解封
+ 解封
+ 解封個人檔案?
+ 確認解封此個人檔案
+ 沒有封鎖的個人檔案
+ 取消
+ 作者
+ 表示喜歡的用戶
+ 刪除這則貼文
+ ?
+ 此動作無法復原
+ 刪除
+ 到底了!
+ 和
+ 被這些人追蹤
+ 其他
+ 其他
+ 每年
+ 每月
+ 每日
+ 我沒有個人檔案
+ 伺服器URL
+ 你確定要登出嗎?
+ 登出?
+ 查看%1$s則留言
+ 留言
+ 沒有留言
+ 沒有喜歡
+ 沒有喜歡的貼文
+ 在地
+ 全球
+ 首頁
+ %1$s個喜歡
+ 搜尋
+ 取消靜音
+ 取消靜音
+ 媒體描述
+ 沒有貼文
+ 提及你
+ 沒有已加書籤的貼文
+ 沒有可顯示的內容
+ 新貼文
+ 發布
+ 替代文字
+ 標題
+ 敏感/NSFW 媒體
+ 內容警告或劇透文本
+ 受眾
+ 未列出
+ 僅限追蹤者
+ 公開
+ 沒有追蹤的標籤
+ 沒有靜音的個人檔案
+ 可見度:%1$s
+ 清理快取
+ 偏好
+ 隱藏敏感內容
+ 關於:%1$s
+ 更多設定
+ 使用內建瀏覽器
No trending profiles
No trending Hashtags
No trending posts
- Upload your first post
- The profiles you follow will appear here
+ 上傳你的第一則貼文
+ 你追蹤的個人資料將在此出現
Explore trending profiles
- Nobody follows you yet
- Empty
+ 沒有人追蹤你
+ 空
Follow profiles or hashtags to fill your home timeline
- No posts
+ 沒有貼文
The Home timeline shows you posts from people and hashtags that you follow
The Local timeline shows posts from all users in your server
The Global timeline shows posts from all users in all servers your server federates with
- This user has not postet anything yet
- You don\'t have any notifications
- view more
- Edit Profile
- Save
- Delete reply
- Reply
- Post
+ 這位用戶尚未發布任何內容
+ 未收到任何通知
+ 查看更多
+ 編輯個人檔案
+ 保存
+ 刪除回覆
+ 回覆
+ 貼文
Pixelfed is a photo and image sharing network on the Fediverse with a photo-oriented interface that includes albums, filters, moments etc.
Mastodon is a free and open source microblogging platform
PeerTube is a tool for sharing online videos developed by Framasoft, a french non-profit.
Lemmy is a selfhosted social link aggregation and discussion platform. It is completely free and open, and not controlled by any company. This means that there is no advertising, tracking, or secret algorithms. Content is organized into communities, so it is easy to subscribe to topics that you are interested in, and ignore others. Voting is used to bring the most interesting items to the top.
Threads is an app from Meta where you can view and share public conversations. You can also post threads, reply to others and follow profiles you are interested in.
- More information
+ 更多資訊
What makes a post trend?
Posts trend if they were posted during the selected timeframe and have many likes.
The trending profiles section lists the profiles on your instance with the most followers. The profiles you already follow are hidden.
- What makes an profile trend?
- What makes a hashtag trend?
- Hashtags trend if many people have used them recently.
- Private profile
- • You won’t see the user in your home feed
+ 什麼造就了個人資料趨勢?
+ 什麼導致了標籤趨勢?
+ 如果最近有很多人使用標籤,那麼該標籤就會成為趨勢。
+ 不公開個人檔案
+ • 您不會在首頁動態中看到該用戶
• You won’t see other people boosting the user
- • You won’t see other people mentioning the user
- • You won’t see the user in public timelines
- The user has no way of knowing they have been muted.
- • You won’t see the user in your home feed
+ • 您不會看到其他人提及該用戶
+ • 您不會在公開時間線上看到該用戶
+ 使用者無法知道他們已被靜音。
+ • 您不會在首頁動態中看到該用戶
• You won’t see other people boosting the user
- • You won’t see other people mentioning the user
- • You won’t see the user in public timelines
- • You won’t see notifications from that user
- • The user is forced to unfollow you
- • The user cannot follow you
- • The user won’t see other people’s boosts of you
- • The user won’t see you in public timelines
- If you and the blocked user are on the same server, the blocked user will not be able to view your posts on your profile while logged in.
- Block
- Block profile?
- Unmute Profile?
- Mute
- Mute Profile?
- sent a dm
- system
- dark
- light
- App theme
- Send message
- Select recipient
- New Direct Message
- Warning
- "Direct messages on Pixelfed are not end-to-end encrypted. Use caution when sharing sensitive data. "
- Confirm
- This is the beginning of your chat with this user. Don\'t forget to be respectful.
- Rate us
- About Pixelix
- Developed by
- Conversations
- Share this collection
- By %1$s
- New Collection
- Creating collections is not yet supported in the pixelfed api, but a new collection can be created in the pixelfed web app:
- New
- Collections
- Follows you
- muted
- blocked
- Message
- All
- Likes
- Reposts
- Edit this post
- Stay updated with your latest notifications from Pixelfed right on your home screen
- Customize app icon
- Change app icon?
- It may take a while until the new icon is shown.
- Change
- mentioned you
+ • 您不會看到其他人提及該用戶
+ • 您不會在公開時間線上看到該用戶
+ • 您將看不到該使用者的通知
+ • 用戶被迫取消追蹤你
+ • 使用者無法追蹤您
+ • 使用者不會看到其他人對您的評價
+ • 用戶不會在公開時間線上看到你
+ 如果您和被封鎖的使用者位於同一台伺服器上,則被封鎖的使用者將無法在登入時查看您個人資料上的貼文。
+ 封鎖
+ 封鎖個人檔案?
+ 解封個人檔案?
+ 靜音
+ 靜音個人檔案?
+ 發送私訊
+ 系統
+ 深色
+ 淺色
+ 應用主題
+ 傳送訊息
+ 選擇接收者
+ 新的Direct訊息
+ 警告
+ "Pixelfed 上的Direct訊息並非端對端加密。分享敏感資料時請務必謹慎。 "
+ 確認
+ 您與該用戶的聊天即將開始。請保持禮貌。
+ 評價我們
+ 關於 Pixelix
+ 開發者
+ 對話
+ 分享這個收藏
+ 由 %1$s
+ 新收藏
+ pixelfed api中尚不支援建立收藏,但可以在pixelfed 網頁應用程式中建立新的收藏:
+ 新
+ 收藏
+ 追蹤了你
+ 已靜音
+ 已封鎖
+ 訊息
+ 全部
+ 喜歡
+ 轉發
+ 編輯貼文
+ 在主畫面隨時取得Pixelfed的最新通知
+ 自定義應用圖示
+ 更改應用圖示?
+ 新圖示可能需要一段時間才會顯示
+ 更改
+ 提及了你
have a look at the newest post from your home timeline, right on your homescreen
- If an icon other than the default icon is selected, two icons will be displayed in your apps drawer.
- Current Profile:
- Other Profiles:
- Add Pixelfed profile
- Download image
- Profile
+ 如果選擇了預設以外的圖示,則應用程式抽屜將有兩個圖示
+ 目前的個人檔案:
+ 其他個人檔案:
+ 新增Pixelfed個人檔案
+ 下載圖片
+ 個人檔案
Inbox
Are you sure you want to remove this Profile?
Remove Profile?
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/App.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/App.kt
index bb1612a5..8e72e1a1 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/App.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/App.kt
@@ -1,7 +1,9 @@
package com.daniebeler.pfpixelix
+import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
@@ -13,6 +15,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.SnackbarHost
import androidx.compose.material.SnackbarHostState
import androidx.compose.material.icons.Icons
@@ -96,8 +99,7 @@ val LocalSnackbarPresenter = compositionLocalOf<(String) -> Unit> {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun App(
- appComponent: AppComponent,
- exitApp: () -> Unit
+ appComponent: AppComponent, exitApp: () -> Unit
) {
val uriHandler = LocalUriHandler.current
DisposableEffect(uriHandler) {
@@ -165,25 +167,17 @@ fun App(
}
})
}
- }
- ) {
+ }) {
Scaffold(
contentWindowInsets = WindowInsets(0),
snackbarHost = { SnackbarHost(snackbarHostState) },
- bottomBar = {
- BottomBar(
- navController = navController,
- openAccountSwitchBottomSheet = {
- showAccountSwitchBottomSheet = true
- },
- )
- },
- content = { paddingValues ->
+ ) { paddingValues ->
+ Box(Modifier.fillMaxSize().padding(paddingValues)) {
val startDestination =
if (activeUser == null) Destination.FirstLogin
else Destination.HomeTabFeeds
NavHost(
- modifier = Modifier.fillMaxSize().padding(paddingValues)
+ modifier = Modifier.fillMaxSize().padding(bottom = 76.dp)
.consumeWindowInsets(WindowInsets.navigationBars),
navController = navController,
startDestination = startDestination,
@@ -193,10 +187,23 @@ fun App(
{ scope.launch { drawerState.open() } },
exitApp
)
- }
- )
+ })
+
+ Box(
+ modifier = Modifier.align(Alignment.BottomCenter)
+ .clip(RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp))
+ .background(MaterialTheme.colorScheme.surface)
+ ) {
+ BottomBar(
+ navController = navController,
+ openAccountSwitchBottomSheet = {
+ showAccountSwitchBottomSheet = true
+ },
+ )
+ }
}
- )
+
+ }
}
}
@@ -235,10 +242,7 @@ private enum class HomeTab(
val label: StringResource
) {
Feeds(
- Destination.HomeTabFeeds,
- Res.drawable.house,
- Res.drawable.house_fill,
- Res.string.home
+ Destination.HomeTabFeeds, Res.drawable.house, Res.drawable.house_fill, Res.string.home
),
Search(
Destination.HomeTabSearch,
@@ -268,8 +272,7 @@ private enum class HomeTab(
@Composable
private fun BottomBar(
- navController: NavHostController,
- openAccountSwitchBottomSheet: () -> Unit
+ navController: NavHostController, openAccountSwitchBottomSheet: () -> Unit
) {
val systemNavigationBarHeight =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
@@ -278,9 +281,7 @@ private fun BottomBar(
val appComponent = LocalAppComponent.current
LaunchedEffect(Unit) {
val authService = appComponent.authService
- authService.activeUser
- .map { authService.getCurrentSession() }
- .collect {
+ authService.activeUser.map { authService.getCurrentSession() }.collect {
avatar = it?.avatar
}
}
@@ -329,10 +330,7 @@ private fun BottomBar(
model = avatar,
error = painterResource(Res.drawable.default_avatar),
contentDescription = "",
- modifier = Modifier
- .height(30.dp)
- .width(30.dp)
- .clip(CircleShape)
+ modifier = Modifier.height(30.dp).width(30.dp).clip(CircleShape)
)
Icon(
Icons.Outlined.UnfoldMore,
@@ -348,14 +346,10 @@ private fun BottomBar(
contentDescription = stringResource(tab.label)
)
}
- },
- selected = isSelected,
- colors = NavigationBarItemDefaults.colors(
+ }, selected = isSelected, colors = NavigationBarItemDefaults.colors(
selectedIconColor = MaterialTheme.colorScheme.inverseSurface,
indicatorColor = Color.Transparent
- ),
- interactionSource = interactionSource,
- onClick = {
+ ), interactionSource = interactionSource, onClick = {
if (!isLongPress) {
if (!isSelected) {
//switch tab
@@ -373,16 +367,14 @@ private fun BottomBar(
if (!isOnRoot) {
//back to root
navController.popBackStack(
- route = tabRoot.route!!,
- inclusive = false
+ route = tabRoot.route!!, inclusive = false
)
} else if (currentDestination.hasRoute()) {
appComponent.searchFieldFocus.focus()
}
}
}
- }
- )
+ })
}
}
}
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/CustomPost.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/CustomPost.kt
index e8d79928..c4ad617d 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/CustomPost.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/CustomPost.kt
@@ -23,14 +23,12 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp
-import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import coil3.compose.AsyncImage
import com.daniebeler.pfpixelix.di.LocalAppComponent
import com.daniebeler.pfpixelix.domain.model.Post
import com.daniebeler.pfpixelix.ui.navigation.Destination
import com.daniebeler.pfpixelix.utils.BlurHashDecoder
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
@@ -60,7 +58,7 @@ fun CustomPost(
?: "LEHLk~WB2yk8pyo0adR*.7kCMdnj"
val blurHashBitmap = remember(firstBlurHash) { BlurHashDecoder.decode(firstBlurHash) }
- Box(modifier = customModifier.aspectRatio(1f)) {
+ Box(modifier = customModifier.clip(RoundedCornerShape(6.dp)).aspectRatio(1f)) {
if (blurHashBitmap != null) {
Image(
blurHashBitmap,
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/FollowButton.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/FollowButton.kt
index 5fa5b15b..85ba8efb 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/FollowButton.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/FollowButton.kt
@@ -70,14 +70,15 @@ private fun IconFollowButton(
)
) {
CircularProgressIndicator(
- modifier = Modifier.size(20.dp)
+ modifier = Modifier.size(20.dp),
+ color = MaterialTheme.colorScheme.onSecondaryContainer
)
}
} else {
IconButton(
onClick = {}, colors = IconButtonDefaults.iconButtonColors(
- containerColor = MaterialTheme.colorScheme.primaryContainer,
- contentColor = MaterialTheme.colorScheme.onPrimaryContainer
+ containerColor = MaterialTheme.colorScheme.primary,
+ contentColor = MaterialTheme.colorScheme.onPrimary
)
) {
CircularProgressIndicator(
@@ -105,8 +106,8 @@ private fun IconFollowButton(
onClick = {
onFollowClick()
}, colors = IconButtonDefaults.iconButtonColors(
- containerColor = MaterialTheme.colorScheme.primaryContainer,
- contentColor = MaterialTheme.colorScheme.onPrimaryContainer
+ containerColor = MaterialTheme.colorScheme.primary,
+ contentColor = MaterialTheme.colorScheme.onPrimary
)
) {
Icon(
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/HomeComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/HomeComposable.kt
index cea13c2c..85d965e9 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/HomeComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/HomeComposable.kt
@@ -6,14 +6,15 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.navigationBars
+import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.windowInsetsPadding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -23,6 +24,8 @@ import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -31,9 +34,11 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.compose.ui.zIndex
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.ui.composables.timelines.global_timeline.GlobalTimelineComposable
import com.daniebeler.pfpixelix.ui.composables.timelines.home_timeline.HomeTimelineComposable
@@ -64,9 +69,14 @@ fun HomeComposable(navController: NavController, openPreferencesDrawer: () -> Un
var showBottomSheet by remember { mutableStateOf(false) }
Scaffold(
- topBar = {
- CenterAlignedTopAppBar(title = {
- Text(stringResource(Res.string.app_name), fontWeight = FontWeight.Bold)
+ contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
+ TopAppBar(
+ title = {
+ Text(
+ stringResource(Res.string.app_name),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
}, navigationIcon = {
IconButton(onClick = { showBottomSheet = true }) {
Icon(
@@ -94,80 +104,89 @@ fun HomeComposable(navController: NavController, openPreferencesDrawer: () -> Un
)
}
}
- })
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}) { paddingValues ->
+ Box(
+ Modifier.fillMaxSize().padding(paddingValues)
+ .background(MaterialTheme.colorScheme.background)
+ ) {
+ PrimaryTabRow(
+ selectedTabIndex = pagerState.currentPage,
+ divider = {},
+ containerColor = MaterialTheme.colorScheme.surfaceContainer,
+ modifier = Modifier.clip(
+ RoundedCornerShape(
+ bottomStart = 24.dp, bottomEnd = 24.dp
+ )
+ ).zIndex(1f)
+ ) {
+ Tab(
+ text = { Text(stringResource(Res.string.home)) },
+ selected = pagerState.currentPage == 0,
+ selectedContentColor = MaterialTheme.colorScheme.primary,
+ unselectedContentColor = MaterialTheme.colorScheme.onBackground,
+ onClick = {
+ scope.launch {
+ pagerState.animateScrollToPage(0)
+ }
+ })
- Column(
- Modifier
- .fillMaxSize()
- .padding(paddingValues)
- ) {
+ Tab(
+ text = { Text(stringResource(Res.string.local)) },
+ selected = pagerState.currentPage == 1,
+ selectedContentColor = MaterialTheme.colorScheme.primary,
+ unselectedContentColor = MaterialTheme.colorScheme.onBackground,
+ onClick = {
+ scope.launch {
+ pagerState.animateScrollToPage(1)
+ }
+ })
- PrimaryTabRow(selectedTabIndex = pagerState.currentPage) {
- Tab(text = { Text(stringResource(Res.string.home)) },
- selected = pagerState.currentPage == 0,
- selectedContentColor = MaterialTheme.colorScheme.primary,
- unselectedContentColor = MaterialTheme.colorScheme.onBackground,
- onClick = {
- scope.launch {
- pagerState.animateScrollToPage(0)
- }
- })
+ Tab(
+ text = { Text(stringResource(Res.string.global)) },
+ selected = pagerState.currentPage == 2,
+ selectedContentColor = MaterialTheme.colorScheme.primary,
+ unselectedContentColor = MaterialTheme.colorScheme.onBackground,
+ onClick = {
+ scope.launch {
+ pagerState.animateScrollToPage(2)
+ }
+ })
+ }
- Tab(text = { Text(stringResource(Res.string.local)) },
- selected = pagerState.currentPage == 1,
- selectedContentColor = MaterialTheme.colorScheme.primary,
- unselectedContentColor = MaterialTheme.colorScheme.onBackground,
- onClick = {
- scope.launch {
- pagerState.animateScrollToPage(1)
+ HorizontalPager(
+ state = pagerState,
+ beyondViewportPageCount = 3,
+ modifier = Modifier.padding(top = 24.dp)
+ .background(MaterialTheme.colorScheme.background).zIndex(0f)
+ ) { tabIndex ->
+ when (tabIndex) {
+ 0 -> Box(modifier = Modifier.fillMaxSize()) {
+ HomeTimelineComposable(navController)
}
- })
- Tab(text = { Text(stringResource(Res.string.global)) },
- selected = pagerState.currentPage == 2,
- selectedContentColor = MaterialTheme.colorScheme.primary,
- unselectedContentColor = MaterialTheme.colorScheme.onBackground,
- onClick = {
- scope.launch {
- pagerState.animateScrollToPage(2)
+ 1 -> Box(modifier = Modifier.fillMaxSize()) {
+ LocalTimelineComposable(navController)
}
- })
- }
- HorizontalPager(
- state = pagerState,
- beyondViewportPageCount = 3,
- modifier = Modifier
- .weight(1f)
- .background(MaterialTheme.colorScheme.background)
- ) { tabIndex ->
- when (tabIndex) {
- 0 -> Box(modifier = Modifier.fillMaxSize()) {
- HomeTimelineComposable(navController)
- }
- 1 -> Box(modifier = Modifier.fillMaxSize()) {
- LocalTimelineComposable(navController)
- }
-
- 2 -> Box(modifier = Modifier.fillMaxSize()) {
- GlobalTimelineComposable(navController)
+ 2 -> Box(modifier = Modifier.fillMaxSize()) {
+ GlobalTimelineComposable(navController)
+ }
}
}
}
- }
}
if (showBottomSheet) {
ModalBottomSheet(
onDismissRequest = {
showBottomSheet = false
- },
- sheetState = sheetState
+ }, sheetState = sheetState
) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 12.dp)
+ modifier = Modifier.fillMaxSize().padding(horizontal = 12.dp)
) {
Column {
Spacer(modifier = Modifier.height(18.dp))
@@ -195,7 +214,7 @@ fun HomeComposable(navController: NavController, openPreferencesDrawer: () -> Un
@Composable
fun SheetItem(header: String, description: String) {
Column {
- Text(text = header, fontSize = 24.sp, fontWeight = FontWeight.Bold)
+ Text(text = header, fontSize = 18.sp, fontWeight = FontWeight.Bold)
Spacer(modifier = Modifier.height(8.dp))
Text(text = description)
Spacer(modifier = Modifier.height(16.dp))
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsGrid.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsGrid.kt
index 2a78c1e4..56a809f5 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsGrid.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsGrid.kt
@@ -2,6 +2,7 @@ package com.daniebeler.pfpixelix.ui.composables
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
@@ -17,6 +18,7 @@ import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.domain.model.Post
@@ -39,6 +41,7 @@ fun InfinitePostsGrid(
emptyMessage: EmptyState,
navController: NavController,
getItemsPaginated: () -> Unit = { },
+ contentPaddingTop: Dp = 0.dp,
before: @Composable (() -> Unit)? = null,
after: @Composable (() -> Unit)? = null,
onRefresh: () -> Unit = { },
@@ -52,13 +55,13 @@ fun InfinitePostsGrid(
PullToRefreshBox(
isRefreshing = isRefreshing, onRefresh = { onRefresh() }, modifier = Modifier.fillMaxSize()
) {
- privateInfinitePostsGrid(items, isLoading, isRefreshing, error, endReached, emptyMessage, navController, getItemsPaginated, before, after, edit, editRemove, onClick)
+ privateInfinitePostsGrid(items, isLoading, isRefreshing, error, endReached, emptyMessage, navController, getItemsPaginated, contentPaddingTop, before, after, edit, editRemove, onClick)
}
} else {
Box(
modifier = Modifier.fillMaxSize()
) {
- privateInfinitePostsGrid(items, isLoading, isRefreshing, error, endReached, emptyMessage, navController, getItemsPaginated, before, after, edit, editRemove, onClick)
+ privateInfinitePostsGrid(items, isLoading, isRefreshing, error, endReached, emptyMessage, navController, getItemsPaginated, contentPaddingTop, before, after, edit, editRemove, onClick)
}
}
}
@@ -73,6 +76,7 @@ fun privateInfinitePostsGrid(
emptyMessage: EmptyState,
navController: NavController,
getItemsPaginated: () -> Unit = { },
+ contentPaddingTop: Dp,
before: @Composable (() -> Unit)? = null,
after: @Composable (() -> Unit)? = null,
edit: Boolean = false,
@@ -86,9 +90,10 @@ fun privateInfinitePostsGrid(
verticalArrangement = Arrangement.spacedBy(4.dp),
modifier = Modifier
.fillMaxSize()
- .padding(horizontal = 12.dp),
+ .padding(horizontal = 4.dp),
state = lazyGridState,
- columns = GridCells.Fixed(3)
+ columns = GridCells.Fixed(3),
+ contentPadding = PaddingValues(top = contentPaddingTop)
) {
if (before != null) {
@@ -98,7 +103,7 @@ fun privateInfinitePostsGrid(
}
item(span = { GridItemSpan(3) }) {
- Spacer(Modifier.height(12.dp))
+ Spacer(Modifier.height(4.dp))
}
itemsIndexed(items) { index, photo ->
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsList.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsList.kt
index 2c2ebe7f..6631ecbd 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsList.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/InfinitePostsList.kt
@@ -38,6 +38,7 @@ fun InfinitePostsList(
changeView: (view: ViewEnum) -> Unit = {},
isFirstItemLarge: Boolean = false,
postsCount: Int? = null,
+ contentPaddingTop: Dp = 0.dp,
contentPaddingBottom: Dp = 4.dp
) {
val lazyListState = rememberLazyListState()
@@ -58,11 +59,7 @@ fun InfinitePostsList(
verticalArrangement = Arrangement.spacedBy(4.dp),
state = lazyListState,
contentPadding = PaddingValues(
- top = if (postsCount != null) {
- 0.dp
- } else {
- 12.dp
- }, bottom = contentPaddingBottom
+ top = contentPaddingTop, bottom = contentPaddingBottom
)
) {
postsCount?.let {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/collection/CollectionComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/collection/CollectionComposable.kt
index feeb3ccb..6740486b 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/collection/CollectionComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/collection/CollectionComposable.kt
@@ -7,19 +7,17 @@ import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.AddCircle
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.MoreVert
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -30,6 +28,8 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -37,8 +37,8 @@ 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.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
@@ -49,11 +49,9 @@ import com.daniebeler.pfpixelix.ui.composables.ButtonRowElement
import com.daniebeler.pfpixelix.ui.composables.InfinitePostsGrid
import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.by
import pixelix.app.generated.resources.cancel
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.confirm
import pixelix.app.generated.resources.open_in_browser
import pixelix.app.generated.resources.open_outline
@@ -77,91 +75,19 @@ fun CollectionComposable(
viewModel.loadData(collectionId)
}
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- if (viewModel.collectionState.collection != null) {
- if (viewModel.editState.editMode) {
- TextField(
- value = viewModel.editState.name,
- singleLine = true,
- onValueChange = { viewModel.editState = viewModel.editState.copy(name = it) },
- modifier = Modifier.fillMaxWidth(),
- shape = RoundedCornerShape(16.dp),
- colors = TextFieldDefaults.colors(
- unfocusedIndicatorColor = Color.Transparent,
- focusedIndicatorColor = Color.Transparent,
- focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
- )
- )
- } else {
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
- Text(
- viewModel.collectionState.collection!!.title, fontWeight = FontWeight.Bold
- )
- Text(
- stringResource(
- Res.string.by, viewModel.collectionState.collection!!.username
- ), fontSize = 12.sp, lineHeight = 6.sp
- )
- }
- }
- }
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- }, actions = {
- if (viewModel.editState.editMode) {
- TextButton(onClick = {
- viewModel.toggleEditMode()
- }) {
- Text(stringResource(Res.string.cancel))
- }
- TextButton(onClick = {
- viewModel.confirmEdit()
- }) {
- Text(stringResource(Res.string.confirm))
- }
- } else {
-
- viewModel.collectionState.collection?.let {
- if (it.username == viewModel.myUsername) {
- IconButton(onClick = {
- viewModel.toggleEditMode()
- }) {
- Icon(
- imageVector = Icons.Outlined.Edit, contentDescription = ""
- )
- }
- }
- }
-
- IconButton(onClick = {
- //Navigate.navigate("settings_screen", navController)
- showBottomSheet = true
- }) {
- Icon(
- imageVector = Icons.Outlined.MoreVert, contentDescription = ""
- )
- }
- }
- })
- }) { paddingValues ->
+ Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top)) { paddingValues ->
Column(
- modifier = Modifier
- .fillMaxSize()
+ modifier = Modifier.fillMaxSize()
+ .padding(top = TopAppBarDefaults.TopAppBarExpandedHeight - 24.dp)
.padding(paddingValues)
) {
- InfinitePostsGrid(items = if (viewModel.editState.editMode) {
- viewModel.editState.editPosts
- } else {
- viewModel.collectionPostsState.posts
- },
+ InfinitePostsGrid(
+ contentPaddingTop = 24.dp,
+ items = if (viewModel.editState.editMode) {
+ viewModel.editState.editPosts
+ } else {
+ viewModel.collectionPostsState.posts
+ },
isLoading = viewModel.collectionPostsState.isLoading,
isRefreshing = viewModel.collectionPostsState.isRefreshing,
error = viewModel.collectionPostsState.error,
@@ -199,25 +125,25 @@ fun CollectionComposable(
ModalBottomSheet(
onDismissRequest = {
showBottomSheet = false
- },
- sheetState = sheetState
+ }, sheetState = sheetState
) {
Column(
modifier = Modifier.padding(bottom = 32.dp)
) {
- ButtonRowElement(icon = Res.drawable.open_outline, text = stringResource(
- Res.string.open_in_browser
- ), onClick = {
- if (viewModel.collectionState.collection != null) {
- viewModel.openUrl(viewModel.collectionState.collection!!.url)
- }
- })
+ ButtonRowElement(
+ icon = Res.drawable.open_outline, text = stringResource(
+ Res.string.open_in_browser
+ ), onClick = {
+ if (viewModel.collectionState.collection != null) {
+ viewModel.openUrl(viewModel.collectionState.collection!!.url)
+ }
+ })
- ButtonRowElement(icon = Res.drawable.share_social_outline,
+ ButtonRowElement(
+ icon = Res.drawable.share_social_outline,
text = stringResource(Res.string.share_this_collection),
- onClick = { viewModel.shareCollectionUrl() }
- )
+ onClick = { viewModel.shareCollectionUrl() })
}
}
@@ -227,13 +153,13 @@ fun CollectionComposable(
ModalBottomSheet(
onDismissRequest = {
showAddPostBottomSheet = false
- },
- sheetState = showAddPostBottomSheetState
+ }, sheetState = showAddPostBottomSheetState
) {
Column(
modifier = Modifier.padding(bottom = 32.dp)
) {
- InfinitePostsGrid(items = viewModel.editState.allPostsExceptCollection,
+ InfinitePostsGrid(
+ items = viewModel.editState.allPostsExceptCollection,
isLoading = viewModel.editState.isLoading,
isRefreshing = false,
error = viewModel.editState.error,
@@ -246,10 +172,96 @@ fun CollectionComposable(
},
onRefresh = {
viewModel.refresh()
- }, onClick = { viewModel.addPostToCollection(it) }, pullToRefresh = false
+ },
+ onClick = { viewModel.addPostToCollection(it) },
+ pullToRefresh = false
)
}
}
}
+
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ if (viewModel.collectionState.collection != null) {
+ if (viewModel.editState.editMode) {
+ TextField(
+ value = viewModel.editState.name,
+ singleLine = true,
+ onValueChange = {
+ viewModel.editState = viewModel.editState.copy(name = it)
+ },
+ modifier = Modifier.fillMaxWidth(),
+ shape = RoundedCornerShape(16.dp),
+ colors = TextFieldDefaults.colors(
+ unfocusedIndicatorColor = Color.Transparent,
+ focusedIndicatorColor = Color.Transparent,
+ focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+ unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
+ } else {
+ Column {
+ Text(
+ viewModel.collectionState.collection!!.title,
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ Text(
+ stringResource(
+ Res.string.by, viewModel.collectionState.collection!!.username
+ ), fontSize = 12.sp, lineHeight = 6.sp
+ )
+ }
+ }
+ }
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, actions = {
+ if (viewModel.editState.editMode) {
+ TextButton(onClick = {
+ viewModel.toggleEditMode()
+ }) {
+ Text(stringResource(Res.string.cancel))
+ }
+ TextButton(onClick = {
+ viewModel.confirmEdit()
+ }) {
+ Text(stringResource(Res.string.confirm))
+ }
+ } else {
+
+ viewModel.collectionState.collection?.let {
+ if (it.username == viewModel.myUsername) {
+ IconButton(onClick = {
+ viewModel.toggleEditMode()
+ }) {
+ Icon(
+ imageVector = Icons.Outlined.Edit, contentDescription = ""
+ )
+ }
+ }
+ }
+
+ IconButton(onClick = {
+ //Navigate.navigate("settings_screen", navController)
+ showBottomSheet = true
+ }) {
+ Icon(
+ imageVector = Icons.Outlined.MoreVert, contentDescription = ""
+ )
+ }
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/chat/ChatComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/chat/ChatComposable.kt
index 5ea37bd9..caa3d11b 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/chat/ChatComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/chat/ChatComposable.kt
@@ -8,14 +8,13 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
@@ -25,6 +24,7 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
@@ -34,9 +34,9 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -57,10 +57,8 @@ import com.daniebeler.pfpixelix.ui.navigation.Destination
import com.daniebeler.pfpixelix.utils.imeAwareInsets
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.beginning_of_chat_note
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.default_avatar
import pixelix.app.generated.resources.message
@@ -77,175 +75,195 @@ fun ChatComposable(
viewModel.getChat(accountId)
}
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- TopAppBar(title = {
- if (viewModel.chatState.chat != null) {
- Row(
- modifier = Modifier.clickable {
- navController.navigate(Destination.Profile(accountId))
- }, verticalAlignment = Alignment.CenterVertically
- ) {
- AsyncImage(
- model = viewModel.chatState.chat!!.avatar,
- error = painterResource(Res.drawable.default_avatar),
- contentDescription = "",
- modifier = Modifier
- .height(46.dp)
- .width(46.dp)
- .clip(CircleShape)
- )
- Spacer(modifier = Modifier.width(10.dp))
-
- Column {
-
- Text(text = viewModel.chatState.chat!!.name ?: "")
- Text(
- text = viewModel.chatState.chat!!.url.substringAfter("https://")
- .substringBefore("/"),
- fontSize = 12.sp,
- lineHeight = 6.sp,
- color = MaterialTheme.colorScheme.primary
- )
- }
- }
- }
+ Box(modifier = Modifier.fillMaxSize()) {
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- })
- }) { paddingValues ->
-
- PullToRefreshBox (
- isRefreshing = viewModel.chatState.isRefreshing,
- onRefresh = { viewModel.getChat(accountId, true) },
- modifier = Modifier
- .imeAwareInsets(90.dp)
- .padding(paddingValues)
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
+ .fillMaxSize()
) {
- Column(
+
+ PullToRefreshBox(
+ isRefreshing = viewModel.chatState.isRefreshing,
+ onRefresh = { viewModel.getChat(accountId, true) },
modifier = Modifier
- .fillMaxSize()
- .padding(12.dp)
+ .imeAwareInsets(90.dp)
) {
- LazyColumn(state = lazyListState,
- modifier = Modifier.weight(1f),
- reverseLayout = true,
- content = {
- if (viewModel.chatState.chat != null && viewModel.chatState.chat?.messages!!.isNotEmpty()) {
-
- items(viewModel.chatState.chat!!.messages, key = {
- it.id
- }) {
- ConversationElementComposable(
- message = it, { viewModel.deleteMessage(it.reportId) }, navController = navController
- )
- }
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(bottom = 16.dp, start = 8.dp, end = 8.dp)
+ ) {
+ LazyColumn(
+ state = lazyListState,
+ modifier = Modifier.weight(1f),
+ reverseLayout = true,
+ contentPadding = PaddingValues(top = 24.dp),
+ content = {
+ if (viewModel.chatState.chat != null && viewModel.chatState.chat?.messages!!.isNotEmpty()) {
- if (viewModel.chatState.isLoading) {
- item {
- CircularProgressIndicator(
- modifier = Modifier
- .fillMaxWidth()
- .height(80.dp)
- .wrapContentSize(Alignment.Center)
+ items(viewModel.chatState.chat!!.messages, key = {
+ it.id
+ }) {
+ ConversationElementComposable(
+ message = it,
+ { viewModel.deleteMessage(it.reportId) },
+ navController = navController
)
}
+
+ if (viewModel.chatState.isLoading) {
+ item {
+ CircularProgressIndicator(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(80.dp)
+ .wrapContentSize(Alignment.Center)
+ )
+ }
+ }
+
+ if (viewModel.chatState.endReached) {
+ item {
+ EndOfListComposable()
+ }
+ }
}
- if (viewModel.chatState.endReached) {
+ if (viewModel.chatState.chat != null && viewModel.chatState.chat?.messages?.isEmpty() == true) {
item {
- EndOfListComposable()
+ Spacer(modifier = Modifier.height(56.dp))
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .clip(
+ RoundedCornerShape(8.dp)
+ )
+ .background(MaterialTheme.colorScheme.primaryContainer)
+ .padding(8.dp)
+ ) {
+ Text(
+ text = stringResource(Res.string.beginning_of_chat_note),
+ textAlign = TextAlign.Center,
+ color = MaterialTheme.colorScheme.onPrimaryContainer,
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
}
}
- }
+ })
- if (viewModel.chatState.chat != null && viewModel.chatState.chat?.messages?.isEmpty() == true) {
- item {
- Spacer(modifier = Modifier.height(56.dp))
- Box(
- modifier = Modifier
+
+ Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.Bottom) {
+ OutlinedTextField(
+ value = viewModel.newMessage,
+ onValueChange = { viewModel.newMessage = it },
+ label = { Text(stringResource(Res.string.message)) },
+ singleLine = false,
+ colors = OutlinedTextFieldDefaults.colors(
+ focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+ unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+ disabledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+ unfocusedBorderColor = MaterialTheme.colorScheme.background
+ ),
+ shape = RoundedCornerShape(12.dp),
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Default),
+ modifier = Modifier.weight(1f)
+ )
+ Spacer(Modifier.width(12.dp))
+ if (viewModel.newMessageState.isLoading) {
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .height(56.dp)
+ .width(56.dp)
+ .padding(0.dp, 0.dp)
+ .clip(RoundedCornerShape(12.dp))
+ .background(MaterialTheme.colorScheme.primary)
+ ) {
+ CircularProgressIndicator(
+ modifier = Modifier.size(24.dp),
+ color = MaterialTheme.colorScheme.onPrimary
+ )
+ }
+ } else {
+ Button(
+ onClick = {
+ viewModel.sendMessage(accountId)
+ },
+ Modifier
+ .height(56.dp)
+ .width(56.dp)
+ .padding(0.dp, 0.dp),
+ shape = RoundedCornerShape(12.dp),
+ contentPadding = PaddingValues(12.dp)
+ ) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.Send,
+ contentDescription = "send",
+ Modifier
+ .fillMaxSize()
.fillMaxWidth()
- .clip(
- RoundedCornerShape(8.dp)
- )
- .background(MaterialTheme.colorScheme.primaryContainer)
- .padding(8.dp)
- ) {
- Text(
- text = stringResource(Res.string.beginning_of_chat_note),
- textAlign = TextAlign.Center,
- color = MaterialTheme.colorScheme.onPrimaryContainer,
- modifier = Modifier.fillMaxWidth()
- )
- }
+ )
}
}
- })
-
-
- Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.Bottom) {
- OutlinedTextField(value = viewModel.newMessage,
- onValueChange = { viewModel.newMessage = it },
- label = { Text(stringResource(Res.string.message)) },
- singleLine = false,
- colors = OutlinedTextFieldDefaults.colors(
- focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- disabledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- unfocusedBorderColor = MaterialTheme.colorScheme.background
- ),
- shape = RoundedCornerShape(12.dp),
- keyboardOptions = KeyboardOptions(imeAction = ImeAction.Default),
- modifier = Modifier.weight(1f)
- )
- Spacer(Modifier.width(12.dp))
- if (viewModel.newMessageState.isLoading) {
- Box(
- contentAlignment = Alignment.Center,
+ }
+
+ ErrorComposable(message = viewModel.chatState.error)
+ }
+ }
+ }
+
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ),
+ title = {
+ if (viewModel.chatState.chat != null) {
+ Row(
+ modifier = Modifier.clickable {
+ navController.navigate(Destination.Profile(accountId))
+ }, verticalAlignment = Alignment.CenterVertically
+ ) {
+ AsyncImage(
+ model = viewModel.chatState.chat!!.avatar,
+ error = painterResource(Res.drawable.default_avatar),
+ contentDescription = "",
modifier = Modifier
- .height(56.dp)
- .width(56.dp)
- .padding(0.dp, 0.dp)
- .clip(RoundedCornerShape(12.dp))
- .background(MaterialTheme.colorScheme.primary)
- ) {
- CircularProgressIndicator(
- modifier = Modifier.size(24.dp),
- color = MaterialTheme.colorScheme.onPrimary
- )
- }
- } else {
- Button(
- onClick = {
- viewModel.sendMessage(accountId)
- },
- Modifier
- .height(56.dp)
- .width(56.dp)
- .padding(0.dp, 0.dp),
- shape = RoundedCornerShape(12.dp),
- contentPadding = PaddingValues(12.dp)
- ) {
- Icon(
- imageVector = Icons.AutoMirrored.Filled.Send,
- contentDescription = "send",
- Modifier
- .fillMaxSize()
- .fillMaxWidth()
+ .height(46.dp)
+ .width(46.dp)
+ .clip(CircleShape)
+ )
+ Spacer(modifier = Modifier.width(10.dp))
+
+ Column {
+
+ Text(text = viewModel.chatState.chat!!.name ?: "")
+ Text(
+ text = viewModel.chatState.chat!!.url.substringAfter("https://")
+ .substringBefore("/"),
+ fontSize = 12.sp,
+ lineHeight = 6.sp,
+ color = MaterialTheme.colorScheme.primary
)
}
}
}
- ErrorComposable(message = viewModel.chatState.error)
- }
- }
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
+
+
InfiniteListHandler(lazyListState = lazyListState) {
viewModel.getChatPaginated(accountId)
}
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/conversations/ConversationsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/conversations/ConversationsComposable.kt
index 7a88c217..8803b19d 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/conversations/ConversationsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/direct_messages/conversations/ConversationsComposable.kt
@@ -4,35 +4,35 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.navigationBars
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
-import androidx.compose.foundation.layout.windowInsetsPadding
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
@@ -47,6 +47,7 @@ import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.InfiniteListHandler
@@ -62,7 +63,6 @@ import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.add_outline
import pixelix.app.generated.resources.cancel
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.confirm
import pixelix.app.generated.resources.conversations
import pixelix.app.generated.resources.direct_messages_encryption_description
@@ -86,86 +86,108 @@ fun ConversationsComposable(
val lazyListState = rememberLazyListState()
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), floatingActionButton = {
- FloatingActionButton(onClick = {
- showNewChatDialog.value = true
- }) {
- Icon(vectorResource(Res.drawable.add_outline), contentDescription = "Add")
+ Box(modifier = Modifier.fillMaxSize()) {
+
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
+
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
+ .fillMaxSize()
+ ) {
+ PullToRefreshBox(
+ isRefreshing = viewModel.conversationsState.isRefreshing,
+ onRefresh = { viewModel.refresh() },
+ modifier = Modifier.fillMaxSize()
+ ) {
+ LazyColumn(
+ state = lazyListState,
+ modifier = Modifier.fillMaxSize(),
+ contentPadding = PaddingValues(top = 28.dp),
+ content = {
+ if (viewModel.conversationsState.conversations.isNotEmpty()) {
+ items(viewModel.conversationsState.conversations, key = {
+ it.id
+ }) {
+ ConversationElementComposable(
+ conversation = it, navController = navController
+ )
+ }
+
+ if (viewModel.conversationsState.isLoading && !viewModel.conversationsState.isRefreshing) {
+ item {
+ CircularProgressIndicator(
+ modifier = Modifier.fillMaxWidth().height(80.dp)
+ .wrapContentSize(Alignment.Center)
+ )
+ }
+ }
+
+ if (viewModel.conversationsState.endReached && viewModel.conversationsState.conversations.size > 10) {
+ item {
+ EndOfListComposable()
+ }
+ }
+ }
+ })
+
+ if (!viewModel.conversationsState.isLoading && viewModel.conversationsState.error.isEmpty() && viewModel.conversationsState.conversations.isEmpty()) {
+ FullscreenEmptyStateComposable(
+ EmptyState(
+ icon = vectorResource(Res.drawable.mail_outline),
+ heading = stringResource(
+ Res.string.you_don_t_have_any_notifications
+ )
+ )
+ )
+ }
+
+ if (!viewModel.conversationsState.isRefreshing && viewModel.conversationsState.conversations.isEmpty()) {
+ LoadingComposable(isLoading = viewModel.conversationsState.isLoading)
+ }
+ ErrorComposable(message = viewModel.conversationsState.error)
+ }
}
- }, topBar = {
- CenterAlignedTopAppBar(title = {
- Text(stringResource(Res.string.conversations), fontWeight = FontWeight.Bold)
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ stringResource(Res.string.conversations),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
}, navigationIcon = {
IconButton(onClick = {
navController.popBackStack()
}) {
Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
)
}
}, actions = {
- IconButton(onClick = { showBottomSheet = true }) {
- Icon(
- imageVector = vectorResource(Res.drawable.help_outline),
- tint = MaterialTheme.colorScheme.error,
- contentDescription = null
- )
- }
- })
- }) { paddingValues ->
- PullToRefreshBox(
- isRefreshing = viewModel.conversationsState.isRefreshing,
- onRefresh = { viewModel.refresh() },
- modifier = Modifier
- .fillMaxSize()
- .padding(paddingValues)
- ) {
- LazyColumn(state = lazyListState, modifier = Modifier.fillMaxSize(), content = {
- if (viewModel.conversationsState.conversations.isNotEmpty()) {
- items(viewModel.conversationsState.conversations, key = {
- it.id
- }) {
- ConversationElementComposable(
- conversation = it, navController = navController
- )
- }
-
- if (viewModel.conversationsState.isLoading && !viewModel.conversationsState.isRefreshing) {
- item {
- CircularProgressIndicator(
- modifier = Modifier
- .fillMaxWidth()
- .height(80.dp)
- .wrapContentSize(Alignment.Center)
- )
- }
- }
-
- if (viewModel.conversationsState.endReached && viewModel.conversationsState.conversations.size > 10) {
- item {
- EndOfListComposable()
- }
- }
+ Row {
+ IconButton(onClick = { showNewChatDialog.value = true }) {
+ Icon(
+ imageVector = vectorResource(Res.drawable.add_outline),
+ contentDescription = null
+ )
}
- })
- if (!viewModel.conversationsState.isLoading && viewModel.conversationsState.error.isEmpty() && viewModel.conversationsState.conversations.isEmpty()) {
- FullscreenEmptyStateComposable(
- EmptyState(
- icon = vectorResource(Res.drawable.mail_outline), heading = stringResource(
- Res.string.you_don_t_have_any_notifications
- )
+ IconButton(onClick = { showBottomSheet = true }) {
+ Icon(
+ imageVector = vectorResource(Res.drawable.help_outline),
+ tint = MaterialTheme.colorScheme.error,
+ contentDescription = null
)
- )
+ }
}
- if (!viewModel.conversationsState.isRefreshing && viewModel.conversationsState.conversations.isEmpty()) {
- LoadingComposable(isLoading = viewModel.conversationsState.isLoading)
- }
- ErrorComposable(message = viewModel.conversationsState.error)
- }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
InfiniteListHandler(lazyListState = lazyListState) {
//viewModel.getNotificationsPaginated()
@@ -175,13 +197,10 @@ fun ConversationsComposable(
ModalBottomSheet(
onDismissRequest = {
showBottomSheet = false
- },
- sheetState = sheetState
+ }, sheetState = sheetState
) {
Box(
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 12.dp)
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp)
) {
Column {
Spacer(modifier = Modifier.height(18.dp))
@@ -228,19 +247,15 @@ private fun CreateNewConversation(
)
if (viewModel.newConversationState.suggestions.isNotEmpty()) {
Box(
- modifier = Modifier
- .padding(top = 4.dp)
- .clip(shape = RoundedCornerShape(12.dp))
+ modifier = Modifier.padding(top = 4.dp).clip(shape = RoundedCornerShape(12.dp))
.background(MaterialTheme.colorScheme.surface)
) {
Column(
modifier = Modifier.padding(12.dp)
) {
viewModel.newConversationState.suggestions.map {
- Box(modifier = Modifier
- .fillMaxWidth()
- .padding(8.dp)
- .clickable {
+ Box(
+ modifier = Modifier.fillMaxWidth().padding(8.dp).clickable {
viewModel.newConversationUsername = TextFieldValue(
it.acct, selection = TextRange(it.acct.length)
)
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/edit_profile/EditProfileComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/edit_profile/EditProfileComposable.kt
index 846fabb5..edcc0255 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/edit_profile/EditProfileComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/edit_profile/EditProfileComposable.kt
@@ -27,7 +27,6 @@ import androidx.compose.material.icons.filled.Done
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -38,6 +37,7 @@ import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
+import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@@ -48,11 +48,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.decodeToImageBitmap
-import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
-import androidx.compose.ui.window.DialogProperties
import androidx.navigation.NavController
import coil3.compose.AsyncImage
import com.attafitamim.krop.core.crop.CropResult
@@ -72,10 +71,8 @@ import io.github.vinceglb.filekit.dialogs.compose.rememberFilePickerLauncher
import io.github.vinceglb.filekit.readBytes
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.bio
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.displayname
import pixelix.app.generated.resources.edit_profile
import pixelix.app.generated.resources.private_profile
@@ -89,234 +86,218 @@ fun EditProfileComposable(
viewModel: EditProfileViewModel = injectViewModel(key = "edit-profile-viewmodel-key") { editProfileViewModel }
) {
- val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
-
Scaffold(
- contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top),
- modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
- topBar = {
- CenterAlignedTopAppBar(
- scrollBehavior = scrollBehavior,
- title = {
- Text(
- text = stringResource(Res.string.edit_profile),
- fontWeight = FontWeight.Bold
- )
- },
- navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline),
- contentDescription = ""
- )
- }
- },
- actions = {
- if (viewModel.firstLoaded) {
- if (viewModel.displayname == (viewModel.accountState.account?.displayname
- ?: "") && viewModel.note == (viewModel.accountState.account?.note
- ?: "") && "https://" + viewModel.website == (viewModel.accountState.account?.website
- ?: "") && viewModel.newAvatar == null && viewModel.privateProfile == viewModel.accountState.account?.locked
- ) {
- if (!viewModel.accountState.isLoading) {
- Button(
- onClick = {},
- modifier = Modifier.width(120.dp),
- shape = RoundedCornerShape(12.dp),
- enabled = false,
- colors = ButtonDefaults.buttonColors(
- disabledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- disabledContentColor = MaterialTheme.colorScheme.onSurface
- )
- ) {
- Text(text = stringResource(Res.string.save))
- }
- }
- } else {
- if (viewModel.accountState.isLoading) {
- Button(
- onClick = {},
- modifier = Modifier.width(120.dp),
- shape = RoundedCornerShape(12.dp)
- ) {
- CircularProgressIndicator(
- modifier = Modifier.size(20.dp),
- color = MaterialTheme.colorScheme.onPrimary
- )
- }
- } else {
- Button(
- onClick = { viewModel.save() },
- modifier = Modifier.width(120.dp),
- shape = RoundedCornerShape(12.dp)
- ) {
- Text(text = stringResource(Res.string.save))
- }
- }
- }
- }
- })
- }) { paddingValues ->
- Box(
- modifier = Modifier
- .padding(paddingValues)
- .fillMaxSize()
+ contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top)
+ ) { paddingValues ->
+ Column(
+ Modifier.padding(paddingValues)
+ .padding(top = TopAppBarDefaults.TopAppBarExpandedHeight - 24.dp).fillMaxSize()
+ .padding(horizontal = 12.dp).verticalScroll(state = rememberScrollState()).imeAwareInsets(90.dp)
) {
- Column(
- Modifier
- .fillMaxSize()
- .padding(12.dp)
- .verticalScroll(state = rememberScrollState())
- .imeAwareInsets(90.dp)
- ) {
- if (viewModel.accountState.account != null) {
+ if (viewModel.accountState.account != null) {
- Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
- val coroutineScope = rememberCoroutineScope()
- val imageCropper = rememberImageCropper()
- val cropState = imageCropper.cropState
- if (cropState != null) {
- ImageCropperFullscreenDialog(cropState)
- }
+ Spacer(Modifier.height(32.dp))
- val filePicker = rememberFilePickerLauncher(
- type = FileKitType.Image, mode = FileKitMode.Single
- ) { file ->
- file ?: return@rememberFilePickerLauncher
- coroutineScope.launch {
- val cropResult = imageCropper.crop {
- ImageBitmapSrc(file.readBytes().decodeToImageBitmap())
- }
- if (cropResult is CropResult.Success) {
- viewModel.newAvatar = cropResult.bitmap
- }
+ Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
+ val coroutineScope = rememberCoroutineScope()
+ val imageCropper = rememberImageCropper()
+ val cropState = imageCropper.cropState
+ if (cropState != null) {
+ ImageCropperFullscreenDialog(cropState)
+ }
+
+ val filePicker = rememberFilePickerLauncher(
+ type = FileKitType.Image, mode = FileKitMode.Single
+ ) { file ->
+ file ?: return@rememberFilePickerLauncher
+ coroutineScope.launch {
+ val cropResult = imageCropper.crop {
+ ImageBitmapSrc(file.readBytes().decodeToImageBitmap())
+ }
+ if (cropResult is CropResult.Success) {
+ viewModel.newAvatar = cropResult.bitmap
}
}
+ }
- val newAvatar = viewModel.newAvatar
- if (newAvatar != null) {
- Image(
- bitmap = newAvatar,
- contentDescription = "",
- modifier = Modifier
- .height(112.dp)
- .width(112.dp)
- .clip(CircleShape)
- .clickable { filePicker.launch() }
- )
- } else {
- AsyncImage(
- model = viewModel.avatarUri.toString(),
- contentDescription = "",
- modifier = Modifier
- .height(112.dp)
- .width(112.dp)
- .clip(CircleShape)
- .clickable { filePicker.launch() }
- )
- }
+ val newAvatar = viewModel.newAvatar
+ if (newAvatar != null) {
+ Image(
+ bitmap = newAvatar,
+ contentDescription = "",
+ modifier = Modifier.height(112.dp).width(112.dp).clip(CircleShape)
+ .clickable { filePicker.launch() })
+ } else {
+ AsyncImage(
+ model = viewModel.avatarUri.toString(),
+ contentDescription = "",
+ modifier = Modifier.height(112.dp).width(112.dp).clip(CircleShape)
+ .clickable { filePicker.launch() })
}
+ }
- Spacer(modifier = Modifier.height(18.dp))
+ Spacer(modifier = Modifier.height(18.dp))
- Row {
- Spacer(Modifier.width(6.dp))
- Text(
- text = stringResource(Res.string.displayname),
- fontWeight = FontWeight.Bold
- )
- }
+ Row {
+ Spacer(Modifier.width(6.dp))
+ Text(
+ text = stringResource(Res.string.displayname), fontWeight = FontWeight.Bold
+ )
+ }
- Spacer(Modifier.height(6.dp))
+ Spacer(Modifier.height(6.dp))
- TextField(
- value = viewModel.displayname,
- singleLine = true,
- onValueChange = { viewModel.displayname = it },
- modifier = Modifier.fillMaxWidth(),
- shape = RoundedCornerShape(16.dp),
- colors = TextFieldDefaults.colors(
- unfocusedIndicatorColor = Color.Transparent,
- focusedIndicatorColor = Color.Transparent,
- focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
- )
+ TextField(
+ value = viewModel.displayname,
+ singleLine = true,
+ onValueChange = { viewModel.displayname = it },
+ modifier = Modifier.fillMaxWidth(),
+ shape = RoundedCornerShape(16.dp),
+ colors = TextFieldDefaults.colors(
+ unfocusedIndicatorColor = Color.Transparent,
+ focusedIndicatorColor = Color.Transparent,
+ focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+ unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
)
+ )
- Spacer(modifier = Modifier.height(18.dp))
+ Spacer(modifier = Modifier.height(18.dp))
- Row {
- Spacer(Modifier.width(6.dp))
- Text(text = stringResource(Res.string.bio), fontWeight = FontWeight.Bold)
- }
+ Row {
+ Spacer(Modifier.width(6.dp))
+ Text(text = stringResource(Res.string.bio), fontWeight = FontWeight.Bold)
+ }
- Spacer(Modifier.height(6.dp))
+ Spacer(Modifier.height(6.dp))
- TextField(
- value = viewModel.note,
- onValueChange = { viewModel.note = it },
- modifier = Modifier.fillMaxWidth(),
- shape = RoundedCornerShape(16.dp),
- colors = TextFieldDefaults.colors(
- unfocusedIndicatorColor = Color.Transparent,
- focusedIndicatorColor = Color.Transparent,
- focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
- )
+ TextField(
+ value = viewModel.note,
+ onValueChange = { viewModel.note = it },
+ modifier = Modifier.fillMaxWidth(),
+ shape = RoundedCornerShape(16.dp),
+ colors = TextFieldDefaults.colors(
+ unfocusedIndicatorColor = Color.Transparent,
+ focusedIndicatorColor = Color.Transparent,
+ focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+ unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
)
+ )
- Spacer(modifier = Modifier.height(18.dp))
+ Spacer(modifier = Modifier.height(18.dp))
- Row {
- Spacer(Modifier.width(6.dp))
- Text(
- text = stringResource(Res.string.website),
- fontWeight = FontWeight.Bold
- )
- }
+ Row {
+ Spacer(Modifier.width(6.dp))
+ Text(
+ text = stringResource(Res.string.website), fontWeight = FontWeight.Bold
+ )
+ }
- Spacer(Modifier.height(6.dp))
+ Spacer(Modifier.height(6.dp))
- TextField(
- value = viewModel.website,
- singleLine = true,
- prefix = {
- Text(text = "https://")
- },
- onValueChange = { viewModel.website = it },
- modifier = Modifier.fillMaxWidth(),
- shape = RoundedCornerShape(16.dp),
- colors = TextFieldDefaults.colors(
- unfocusedIndicatorColor = Color.Transparent,
- focusedIndicatorColor = Color.Transparent,
- focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
- )
+ TextField(
+ value = viewModel.website,
+ singleLine = true,
+ prefix = {
+ Text(text = "https://")
+ },
+ onValueChange = { viewModel.website = it },
+ modifier = Modifier.fillMaxWidth(),
+ shape = RoundedCornerShape(16.dp),
+ colors = TextFieldDefaults.colors(
+ unfocusedIndicatorColor = Color.Transparent,
+ focusedIndicatorColor = Color.Transparent,
+ focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+ unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer
)
+ )
- Spacer(modifier = Modifier.height(18.dp))
-
- Row(verticalAlignment = Alignment.CenterVertically) {
- Spacer(Modifier.width(6.dp))
- Text(
- text = stringResource(Res.string.private_profile),
- fontWeight = FontWeight.Bold
- )
- Spacer(modifier = Modifier.weight(1f))
- Switch(
- checked = viewModel.privateProfile,
- onCheckedChange = { viewModel.privateProfile = it })
- }
+ Spacer(modifier = Modifier.height(18.dp))
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Spacer(Modifier.width(6.dp))
+ Text(
+ text = stringResource(Res.string.private_profile),
+ fontWeight = FontWeight.Bold
+ )
+ Spacer(modifier = Modifier.weight(1f))
+ Switch(
+ checked = viewModel.privateProfile,
+ onCheckedChange = { viewModel.privateProfile = it })
}
+ Spacer(Modifier.height(24.dp))
}
+
}
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ text = stringResource(Res.string.edit_profile),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, actions = {
+ if (viewModel.firstLoaded) {
+ if (viewModel.displayname == (viewModel.accountState.account?.displayname
+ ?: "") && viewModel.note == (viewModel.accountState.account?.note
+ ?: "") && "https://" + viewModel.website == (viewModel.accountState.account?.website
+ ?: "") && viewModel.newAvatar == null && viewModel.privateProfile == viewModel.accountState.account?.locked
+ ) {
+ if (!viewModel.accountState.isLoading) {
+ Button(
+ onClick = {},
+ modifier = Modifier.width(120.dp),
+ shape = RoundedCornerShape(12.dp),
+ enabled = false,
+ colors = ButtonDefaults.buttonColors(
+ disabledContainerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
+ disabledContentColor = MaterialTheme.colorScheme.onSurface
+ )
+ ) {
+ Text(text = stringResource(Res.string.save))
+ }
+ }
+ } else {
+ if (viewModel.accountState.isLoading) {
+ Button(
+ onClick = {},
+ modifier = Modifier.width(120.dp),
+ shape = RoundedCornerShape(12.dp)
+ ) {
+ CircularProgressIndicator(
+ modifier = Modifier.size(20.dp),
+ color = MaterialTheme.colorScheme.onPrimary
+ )
+ }
+ } else {
+ Button(
+ onClick = { viewModel.save() },
+ modifier = Modifier.width(120.dp),
+ shape = RoundedCornerShape(12.dp)
+ ) {
+ Text(text = stringResource(Res.string.save))
+ }
+ }
+ }
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
+
}
}
@@ -339,34 +320,32 @@ private fun ImageCropperFullscreenDialog(
Scaffold(
contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top),
topBar = {
- CenterAlignedTopAppBar(
- title = {},
- navigationIcon = {
+ TopAppBar(
+ title = {}, navigationIcon = {
androidx.compose.material.IconButton(onClick = { state.done(accept = false) }) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, null)
}
- },
- actions = {
+ }, actions = {
IconButton(onClick = { state.reset() }) {
Icon(Icons.Default.Refresh, null)
}
IconButton(
- onClick = { state.done(accept = true) },
- enabled = !state.accepted
+ onClick = { state.done(accept = true) }, enabled = !state.accepted
) {
Icon(Icons.Default.Done, null)
}
- }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
)
- }
- ) { paddingValues ->
+ }) { paddingValues ->
Box(
modifier = Modifier.fillMaxSize().padding(paddingValues)
) {
CropperPreview(state = state, modifier = Modifier.fillMaxSize())
- Box(Modifier
- .fillMaxSize()
- .windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Bottom))
+ Box(
+ Modifier.fillMaxSize()
+ .windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Bottom))
) {
DefaultControls(state)
}
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/ExploreComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/ExploreComposable.kt
index 745224c2..5ec49301 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/ExploreComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/ExploreComposable.kt
@@ -105,12 +105,15 @@ fun ExploreComposable(
Box(Modifier
.fillMaxSize()
- .background(MaterialTheme.colorScheme.surface)
+ .background(MaterialTheme.colorScheme.surfaceContainer)
.semantics { isTraversalGroup = true }) {
SearchBar(
modifier = Modifier
.align(Alignment.TopCenter)
.semantics { traversalIndex = 0f },
+ colors = SearchBarDefaults.colors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainerHigh
+ ),
inputField = {
SearchBarDefaults.InputField(
query = textFieldState.text.toString(),
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/TrendingComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/TrendingComposable.kt
index 2e76b331..3955419a 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/TrendingComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/TrendingComposable.kt
@@ -4,14 +4,12 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
@@ -26,6 +24,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.ui.composables.SheetItem
@@ -59,15 +58,42 @@ fun TrendingComposable(navController: NavController, initialPage: Int) {
val range by remember { mutableStateOf("daily") }
- Column(
- Modifier.fillMaxSize()
+ Box(
+ Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
+ HorizontalPager(
+ state = pagerState,
+ beyondViewportPageCount = 3,
+ modifier = Modifier.padding(top = 24.dp).background(MaterialTheme.colorScheme.background)
+ ) { tabIndex ->
+ when (tabIndex) {
+ 0 -> Box(modifier = Modifier.fillMaxSize()) {
+ TrendingPostsComposable(range, navController = navController)
+ }
- PrimaryTabRow(selectedTabIndex = pagerState.currentPage) {
- Tab(text = { Text(stringResource(Res.string.posts)) },
+ 1 -> Box(modifier = Modifier.fillMaxSize()) {
+ TrendingAccountsComposable(navController = navController)
+ }
+
+ 2 -> Box(modifier = Modifier.fillMaxSize()) {
+ TrendingHashtagsComposable(navController = navController)
+ }
+
+ }
+ }
+
+ PrimaryTabRow(
+ selectedTabIndex = pagerState.currentPage,
+ divider = {},
+ containerColor = MaterialTheme.colorScheme.surfaceContainer,
+ modifier = Modifier
+ .clip(RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp))
+ ) {
+ Tab(
+ text = { Text(stringResource(Res.string.posts)) },
selected = pagerState.currentPage == 0,
selectedContentColor = MaterialTheme.colorScheme.primary,
- unselectedContentColor = MaterialTheme.colorScheme.onBackground,
+ unselectedContentColor = MaterialTheme.colorScheme.onSurface,
onClick = {
scope.launch {
pagerState.animateScrollToPage(0)
@@ -75,62 +101,38 @@ fun TrendingComposable(navController: NavController, initialPage: Int) {
})
- Tab(text = { Text(stringResource(Res.string.accounts)) },
+ Tab(
+ text = { Text(stringResource(Res.string.accounts)) },
selected = pagerState.currentPage == 1,
selectedContentColor = MaterialTheme.colorScheme.primary,
- unselectedContentColor = MaterialTheme.colorScheme.onBackground,
+ unselectedContentColor = MaterialTheme.colorScheme.onSurface,
onClick = {
scope.launch {
pagerState.animateScrollToPage(1)
}
})
- Tab(text = { Text(stringResource(Res.string.hashtags)) },
+ Tab(
+ text = { Text(stringResource(Res.string.hashtags)) },
selected = pagerState.currentPage == 2,
selectedContentColor = MaterialTheme.colorScheme.primary,
- unselectedContentColor = MaterialTheme.colorScheme.onBackground,
+ unselectedContentColor = MaterialTheme.colorScheme.onSurface,
onClick = {
scope.launch {
pagerState.animateScrollToPage(2)
}
})
}
-
- HorizontalPager(
- state = pagerState,
- beyondViewportPageCount = 3,
- modifier = Modifier
- .weight(1f)
- .background(MaterialTheme.colorScheme.background)
- ) { tabIndex ->
- when (tabIndex) {
- 0 -> Box(modifier = Modifier.fillMaxSize()) {
- TrendingPostsComposable(range, navController = navController)
- }
-
- 1 -> Box(modifier = Modifier.fillMaxSize()) {
- TrendingAccountsComposable(navController = navController)
- }
-
- 2 -> Box(modifier = Modifier.fillMaxSize()) {
- TrendingHashtagsComposable(navController = navController)
- }
-
- }
- }
}
if (showBottomSheet) {
ModalBottomSheet(
onDismissRequest = {
showBottomSheet = false
- },
- sheetState = sheetState
+ }, sheetState = sheetState
) {
Box(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 12.dp)
+ modifier = Modifier.fillMaxSize().padding(horizontal = 12.dp)
) {
Column {
Spacer(modifier = Modifier.height(18.dp))
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountElement.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountElement.kt
index 55035291..db35b04a 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountElement.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountElement.kt
@@ -1,5 +1,6 @@
package com.daniebeler.pfpixelix.ui.composables.explore.trending.trending_accounts
+import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -9,6 +10,7 @@ import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
@@ -33,9 +35,8 @@ fun TrendingAccountElement(
}
Column(
- Modifier
- .padding(12.dp)
- .fillMaxWidth()
+ Modifier.clip(RoundedCornerShape(16.dp))
+ .background(MaterialTheme.colorScheme.surfaceContainerLow).padding(8.dp).fillMaxWidth()
.clickable {
navController.navigate(Destination.Profile(account.id))
}) {
@@ -47,8 +48,8 @@ fun TrendingAccountElement(
text = account.note,
mentions = null,
navController = navController,
- modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), openUrl = { url -> viewModel.openUrl(url) }
- )
+ modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
+ openUrl = { url -> viewModel.openUrl(url) })
}
NonlazyGrid(itemCount = minOf(9, viewModel.postsState.posts.size)) {
@@ -63,13 +64,15 @@ fun TrendingAccountElement(
@Composable
private fun NonlazyGrid(
- itemCount: Int,
- content: @Composable (Int) -> Unit
+ itemCount: Int, content: @Composable (Int) -> Unit
) {
val columns = 3
- Column(modifier = Modifier.clip(RoundedCornerShape(12.dp)), verticalArrangement = Arrangement.spacedBy(4.dp)) {
+ Column(
+ modifier = Modifier.clip(RoundedCornerShape(12.dp)),
+ verticalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
var rows = (itemCount / columns)
if (itemCount.mod(columns) > 0) {
rows += 1
@@ -78,14 +81,11 @@ private fun NonlazyGrid(
for (rowId in 0 until rows) {
val firstIndex = rowId * columns
- Row (horizontalArrangement = Arrangement.spacedBy(4.dp)) {
+ Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
for (columnId in 0 until columns) {
val index = firstIndex + columnId
Box(
- modifier = Modifier
- .fillMaxWidth()
- .aspectRatio(1f)
- .weight(1f)
+ modifier = Modifier.fillMaxWidth().aspectRatio(1f).weight(1f)
) {
if (index < itemCount) {
content(index)
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountsComposable.kt
index 3a865a98..82cc2669 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_accounts/TrendingAccountsComposable.kt
@@ -1,7 +1,9 @@
package com.daniebeler.pfpixelix.ui.composables.explore.trending.trending_accounts
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -29,7 +31,8 @@ fun TrendingAccountsComposable(
isRefreshing = viewModel.trendingAccountsState.isRefreshing,
onRefresh = { viewModel.getTrendingAccountsState(true) },
) {
- LazyColumn(modifier = Modifier.fillMaxSize(),
+ LazyColumn(modifier = Modifier.fillMaxSize().padding(horizontal = 4.dp),
+ contentPadding = PaddingValues(top = 32.dp, bottom = 12.dp),
verticalArrangement = Arrangement.spacedBy(20.dp),
content = {
items(viewModel.trendingAccountsState.trendingAccounts, key = {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagElement.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagElement.kt
index 8a1e85be..6b417cbd 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagElement.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagElement.kt
@@ -1,5 +1,6 @@
package com.daniebeler.pfpixelix.ui.composables.explore.trending.trending_hashtags
+import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -49,6 +50,8 @@ fun TrendingHashtagElement(
Column(
Modifier
+ .clip(RoundedCornerShape(16.dp))
+ .background(MaterialTheme.colorScheme.surfaceContainerLow)
.padding(vertical = 8.dp)
.fillMaxWidth()
.clickable {
@@ -73,6 +76,9 @@ fun TrendingHashtagElement(
}
}
+ Box(modifier = Modifier.padding(horizontal = 8.dp).clip(
+ RoundedCornerShape(12.dp)
+ )) {
LazyHorizontalGrid(
rows = GridCells.Fixed(3),
horizontalArrangement = Arrangement.spacedBy(4.dp),
@@ -80,10 +86,6 @@ fun TrendingHashtagElement(
modifier = Modifier.height(428.dp)
) {
- item(span = { GridItemSpan(3) }) {
- Spacer(Modifier.width(12.dp))
- }
-
itemsIndexed(viewModel.postsState.posts) { index, post ->
val postsCount = viewModel.postsState.posts.size;
@@ -119,11 +121,7 @@ fun TrendingHashtagElement(
CustomPost(post = post, navController = navController, customModifier = customModifier)
}
}
-
- item(span = { GridItemSpan(3) }) {
- Spacer(Modifier.width(12.dp))
- }
}
-
+ }
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagsComposable.kt
index a65dcc79..3ffdfede 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_hashtags/TrendingHashtagsComposable.kt
@@ -1,13 +1,16 @@
package com.daniebeler.pfpixelix.ui.composables.explore.trending.trending_hashtags
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
-import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
@@ -18,7 +21,7 @@ import org.jetbrains.compose.resources.stringResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.no_trending_hashtags
-@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TrendingHashtagsComposable(
navController: NavController,
@@ -28,26 +31,30 @@ fun TrendingHashtagsComposable(
isRefreshing = viewModel.trendingHashtagsState.isRefreshing,
onRefresh = { viewModel.getTrendingHashtags(true) },
) {
- LazyColumn(modifier = Modifier
- .fillMaxSize(), content = {
- items(viewModel.trendingHashtagsState.trendingHashtags, key = {
- it.hashtag ?: ""
- }) {
- TrendingHashtagElement(hashtag = it, navController = navController)
- }
- })
+ LazyColumn(
+ modifier = Modifier.fillMaxSize().padding(horizontal = 4.dp),
+ contentPadding = PaddingValues(top = 32.dp, bottom = 12.dp),
+ verticalArrangement = Arrangement.spacedBy(20.dp),
+ content = {
+ items(viewModel.trendingHashtagsState.trendingHashtags, key = {
+ it.hashtag ?: ""
+ }) {
+ TrendingHashtagElement(hashtag = it, navController = navController)
+ }
+ })
- if (viewModel.trendingHashtagsState.trendingHashtags.isEmpty()) {
- if (viewModel.trendingHashtagsState.isLoading && !viewModel.trendingHashtagsState.isRefreshing) {
- FullscreenLoadingComposable()
- }
+ if (viewModel.trendingHashtagsState.trendingHashtags.isEmpty()) {
+ if (viewModel.trendingHashtagsState.isLoading && !viewModel.trendingHashtagsState.isRefreshing) {
+ FullscreenLoadingComposable()
+ }
- if (viewModel.trendingHashtagsState.error.isNotEmpty()) {
- FullscreenErrorComposable(message = viewModel.trendingHashtagsState.error)
- }
+ if (viewModel.trendingHashtagsState.error.isNotEmpty()) {
+ FullscreenErrorComposable(message = viewModel.trendingHashtagsState.error)
+ }
- if (!viewModel.trendingHashtagsState.isLoading && viewModel.trendingHashtagsState.error.isEmpty()) {
- FullscreenEmptyStateComposable(EmptyState(heading = stringResource(Res.string.no_trending_hashtags)))
+ if (!viewModel.trendingHashtagsState.isLoading && viewModel.trendingHashtagsState.error.isEmpty()) {
+ FullscreenEmptyStateComposable(EmptyState(heading = stringResource(Res.string.no_trending_hashtags)))
+ }
}
}
-}}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_posts/TrendingPostsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_posts/TrendingPostsComposable.kt
index e9cfe0b3..869a939f 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_posts/TrendingPostsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/explore/trending/trending_posts/TrendingPostsComposable.kt
@@ -1,28 +1,15 @@
package com.daniebeler.pfpixelix.ui.composables.explore.trending.trending_posts
import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.navigationBars
-import androidx.compose.foundation.layout.only
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
-import androidx.compose.foundation.layout.waterfall
-import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
-import com.daniebeler.pfpixelix.ui.composables.InfinitePostsGrid
import com.daniebeler.pfpixelix.ui.composables.InfinitePostsList
import com.daniebeler.pfpixelix.ui.composables.profile.ViewEnum
-import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
-import org.jetbrains.compose.resources.stringResource
-import pixelix.app.generated.resources.Res
-import pixelix.app.generated.resources.no_trending_posts
@Composable
fun TrendingPostsComposable(
@@ -51,7 +38,8 @@ fun TrendingPostsComposable(
onRefresh = { viewModel.getTrendingPosts(range, true) },
navController = navController,
postGetsUpdated = { },
- contentPaddingBottom = 10.dp
+ contentPaddingTop = 32.dp,
+ contentPaddingBottom = 20.dp
)
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersComposable.kt
index d2dd4f1b..21e37b59 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersComposable.kt
@@ -1,19 +1,18 @@
package com.daniebeler.pfpixelix.ui.composables.followers
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Groups
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.key.Key.Companion.R
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
@@ -36,7 +35,7 @@ fun FollowersComposable(
) {
val lazyListState = rememberLazyListState()
- LazyColumn(state = lazyListState, content = {
+ LazyColumn(state = lazyListState, contentPadding = PaddingValues(top = 24.dp), content = {
items(viewModel.followersState.followers, key = {
it.id
}) {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersMainComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersMainComposable.kt
index 2b08cf37..5005fb8a 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersMainComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowersMainComposable.kt
@@ -13,7 +13,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -22,22 +24,23 @@ import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.compose.ui.zIndex
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.followers
import pixelix.app.generated.resources.following
@@ -65,14 +68,17 @@ fun FollowersMainComposable(
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top),
+ Scaffold(
+ contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top),
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
- CenterAlignedTopAppBar(title = {
- Column (horizontalAlignment = Alignment.CenterHorizontally) {
+ TopAppBar(
+ title = {
+ Column {
Text(
text = viewModel.accountState.account?.username ?: "",
- fontWeight = FontWeight.Bold
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
)
Text(
text = viewModel.accountState.account?.url?.substringAfter("https://")
@@ -84,30 +90,42 @@ fun FollowersMainComposable(
navController.popBackStack()
}) {
Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+ contentDescription = ""
)
}
- })
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}) { paddingValues ->
- Column(
- Modifier
- .fillMaxSize()
- .padding(paddingValues)
+ Box(
+ Modifier.fillMaxSize().padding(paddingValues)
) {
- PrimaryTabRow(selectedTabIndex = pagerState.currentPage) {
- Tab(text = {
- if (viewModel.accountState.account != null) {
- Text(
- viewModel.accountState.account?.followersCount.toString() + " " + stringResource(
- Res.string.followers
+ PrimaryTabRow(
+ selectedTabIndex = pagerState.currentPage,
+ divider = {},
+ containerColor = MaterialTheme.colorScheme.surfaceContainer,
+ modifier = Modifier.clip(
+ RoundedCornerShape(
+ bottomStart = 24.dp, bottomEnd = 24.dp
+ )
+ ).zIndex(1f)
+ ) {
+ Tab(
+ text = {
+ if (viewModel.accountState.account != null) {
+ Text(
+ viewModel.accountState.account?.followersCount.toString() + " " + stringResource(
+ Res.string.followers
+ )
)
- )
- } else {
- Text(text = stringResource(Res.string.followers))
- }
- },
+ } else {
+ Text(text = stringResource(Res.string.followers))
+ }
+ },
selected = pagerState.currentPage == 0,
selectedContentColor = MaterialTheme.colorScheme.primary,
unselectedContentColor = MaterialTheme.colorScheme.onBackground,
@@ -117,17 +135,18 @@ fun FollowersMainComposable(
}
})
- Tab(text = {
- if (viewModel.accountState.account != null) {
- Text(
- viewModel.accountState.account?.followingCount.toString() + " " + stringResource(
- Res.string.following
+ Tab(
+ text = {
+ if (viewModel.accountState.account != null) {
+ Text(
+ viewModel.accountState.account?.followingCount.toString() + " " + stringResource(
+ Res.string.following
+ )
)
- )
- } else {
- Text(text = stringResource(Res.string.following))
- }
- },
+ } else {
+ Text(text = stringResource(Res.string.following))
+ }
+ },
selected = pagerState.currentPage == 1,
selectedContentColor = MaterialTheme.colorScheme.primary,
unselectedContentColor = MaterialTheme.colorScheme.onBackground,
@@ -140,9 +159,8 @@ fun FollowersMainComposable(
HorizontalPager(
state = pagerState,
- modifier = Modifier
- .weight(1f)
- .background(MaterialTheme.colorScheme.background)
+ modifier = Modifier.padding(top = 24.dp)
+ .background(MaterialTheme.colorScheme.background).zIndex(0f)
) { tabIndex ->
when (tabIndex) {
0 -> Box(modifier = Modifier.fillMaxSize()) {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowingComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowingComposable.kt
index af02847d..dae0db7b 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowingComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/followers/FollowingComposable.kt
@@ -1,12 +1,12 @@
package com.daniebeler.pfpixelix.ui.composables.followers
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Groups
import androidx.compose.material3.CircularProgressIndicator
@@ -30,7 +30,6 @@ import pixelix.app.generated.resources.explore_trending_profiles
import pixelix.app.generated.resources.not_following_anyone
import pixelix.app.generated.resources.the_profiles_you_follow_will_appear_here
-@OptIn(ExperimentalMaterialApi::class)
@Composable
fun FollowingComposable(
navController: NavController,
@@ -38,7 +37,7 @@ fun FollowingComposable(
) {
val lazyListState = rememberLazyListState()
- LazyColumn(state = lazyListState, content = {
+ LazyColumn(state = lazyListState, contentPadding = PaddingValues(top = 24.dp), content = {
items(viewModel.followingState.following, key = {
it.id
}) {
@@ -48,9 +47,7 @@ fun FollowingComposable(
if (viewModel.followingState.following.isNotEmpty() && viewModel.followingState.isLoading && !viewModel.followingState.isRefreshing) {
item {
CircularProgressIndicator(
- modifier = Modifier
- .fillMaxWidth()
- .height(80.dp)
+ modifier = Modifier.fillMaxWidth().height(80.dp)
.wrapContentSize(Alignment.Center)
)
}
@@ -65,13 +62,13 @@ fun FollowingComposable(
if (!viewModel.followingState.isLoading && viewModel.followingState.error.isEmpty() && viewModel.followingState.following.isEmpty()) {
- val message = if (viewModel.loggedInAccountId == viewModel.accountId)
- stringResource(Res.string.the_profiles_you_follow_will_appear_here)
- else
- stringResource(Res.string.not_following_anyone)
+ val message =
+ if (viewModel.loggedInAccountId == viewModel.accountId) stringResource(Res.string.the_profiles_you_follow_will_appear_here)
+ else stringResource(Res.string.not_following_anyone)
FullscreenEmptyStateComposable(
- emptyState = EmptyState(icon = Icons.Outlined.Groups,
+ emptyState = EmptyState(
+ icon = Icons.Outlined.Groups,
heading = stringResource(Res.string.empty),
message = message,
buttonText = stringResource(Res.string.explore_trending_profiles),
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/mention/MentionComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/mention/MentionComposable.kt
index fa4ea8f7..f8518bf6 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/mention/MentionComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/mention/MentionComposable.kt
@@ -17,12 +17,12 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -73,7 +73,7 @@ fun MentionComposable(
}
Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
+ TopAppBar(title = {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = stringResource(Res.string.post), fontWeight = FontWeight.Bold
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/newpost/NewPostComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/newpost/NewPostComposable.kt
index 34043e74..9874b18c 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/newpost/NewPostComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/newpost/NewPostComposable.kt
@@ -15,14 +15,13 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.pager.HorizontalPager
@@ -37,7 +36,6 @@ import androidx.compose.material.icons.outlined.Check
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
@@ -46,12 +44,13 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
@@ -61,17 +60,17 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
-import co.touchlab.kermit.Logger
import coil3.compose.AsyncImage
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.domain.model.Visibility
-import com.daniebeler.pfpixelix.ui.composables.states.ErrorComposable
import com.daniebeler.pfpixelix.ui.composables.states.ErrorComposableDialog
import com.daniebeler.pfpixelix.ui.composables.states.LoadingComposable
import com.daniebeler.pfpixelix.ui.composables.textfield_location.TextFieldLocationsComposable
@@ -120,174 +119,202 @@ fun NewPostComposable(
}
}
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(text = stringResource(Res.string.new_post), fontWeight = FontWeight.Bold)
- }, actions = {
- Button(
- onClick = { showReleaseAlert = true },
- enabled = (viewModel.images.isNotEmpty() && viewModel.images.none { it.isLoading })
- ) {
- Text(text = stringResource(Res.string.release))
- }
- })
- }) { paddingValues ->
- Box {
- Column(
- Modifier.padding(paddingValues).imeAwareInsets(90.dp).fillMaxSize()
- .verticalScroll(rememberScrollState()),
- verticalArrangement = Arrangement.spacedBy(16.dp)
- ) {
- ImagesPager(viewModel.images,
- { index, altText ->
- viewModel.updateAltTextVariable(
- index, altText
- )
- },
- { index -> viewModel.moveMediaAttachmentUp(index) },
- { index -> viewModel.moveMediaAttachmentDown(index) },
- { index -> viewModel.deleteMedia(index) },
- { kmpUri: KmpUri -> viewModel.addImage(kmpUri) })
+ Box(modifier = Modifier.fillMaxSize()) {
+
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
- NewPostTextField(
- value = viewModel.caption,
- onChange = { viewModel.caption = it },
- label = stringResource(Res.string.caption)
- )
- NewPostPref(leadingIcon = Res.drawable.browsers_outline,
- title = stringResource(Res.string.sensitive_nsfw_media),
- trailingContent = {
- Switch(checked = viewModel.sensitive,
- onCheckedChange = { viewModel.sensitive = it })
- })
- AnimatedVisibility(
- visible = viewModel.sensitive,
- enter = slideInVertically() + fadeIn(),
- exit = shrinkVertically(animationSpec = spring(stiffness = Spring.StiffnessMedium)) + fadeOut(),
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
+ .fillMaxSize()
+ ) {
+ Box {
+ Column(
+ Modifier.imeAwareInsets(90.dp).fillMaxSize()
+ .verticalScroll(rememberScrollState()),
+ verticalArrangement = Arrangement.spacedBy(16.dp)
+ ) {
+ Spacer(Modifier.height(24.dp))
+
+ ImagesPager(
+ viewModel.images,
+ { index, altText ->
+ viewModel.updateAltTextVariable(
+ index, altText
+ )
+ },
+ { index -> viewModel.moveMediaAttachmentUp(index) },
+ { index -> viewModel.moveMediaAttachmentDown(index) },
+ { index -> viewModel.deleteMedia(index) },
+ { kmpUri: KmpUri -> viewModel.addImage(kmpUri) })
+
+ Column(
+ Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(10.dp)
) {
NewPostTextField(
- value = viewModel.sensitiveText,
- onChange = { viewModel.sensitiveText = it },
- label = stringResource(Res.string.content_warning_or_spoiler_text)
+ value = viewModel.caption,
+ onChange = { viewModel.caption = it },
+ label = stringResource(Res.string.caption)
)
- }
- NewPostPref(leadingIcon = Res.drawable.browsers_outline,
- title = stringResource(Res.string.audience),
- trailingContent = {
- Box {
- OutlinedButton(onClick = { expanded = !expanded }) {
- val buttonText: String = when (viewModel.audience) {
- Visibility.PUBLIC -> stringResource(Res.string.audience_public)
- Visibility.UNLISTED -> stringResource(Res.string.unlisted)
- Visibility.PRIVATE -> stringResource(Res.string.followers_only)
- else -> ""
+ NewPostPref(
+ leadingIcon = Res.drawable.browsers_outline,
+ title = stringResource(Res.string.sensitive_nsfw_media),
+ trailingContent = {
+ Switch(
+ checked = viewModel.sensitive,
+ onCheckedChange = { viewModel.sensitive = it })
+ })
+ AnimatedVisibility(
+ visible = viewModel.sensitive,
+ enter = slideInVertically() + fadeIn(),
+ exit = shrinkVertically(animationSpec = spring(stiffness = Spring.StiffnessMedium)) + fadeOut(),
+ ) {
+ NewPostTextField(
+ value = viewModel.sensitiveText,
+ onChange = { viewModel.sensitiveText = it },
+ label = stringResource(Res.string.content_warning_or_spoiler_text)
+ )
+ }
+ NewPostPref(
+ leadingIcon = Res.drawable.browsers_outline,
+ title = stringResource(Res.string.audience),
+ trailingContent = {
+ Box {
+ OutlinedButton(onClick = { expanded = !expanded }) {
+ val buttonText: String = when (viewModel.audience) {
+ Visibility.PUBLIC -> stringResource(Res.string.audience_public)
+ Visibility.UNLISTED -> stringResource(Res.string.unlisted)
+ Visibility.PRIVATE -> stringResource(Res.string.followers_only)
+ else -> ""
+ }
+ Text(text = buttonText)
+ }
+ DropdownMenu(
+ expanded = expanded,
+ onDismissRequest = { expanded = false }) {
+ DropdownMenuItem(
+ text = { Text(stringResource(Res.string.audience_public)) },
+ onClick = { viewModel.audience = Visibility.PUBLIC },
+ trailingIcon = {
+ if (viewModel.audience == Visibility.PUBLIC) {
+ Icon(
+ imageVector = Icons.Outlined.Check,
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.primary
+ )
+ }
+ })
+ DropdownMenuItem(
+ text = { Text(stringResource(Res.string.unlisted)) },
+ onClick = { viewModel.audience = Visibility.UNLISTED },
+ trailingIcon = {
+ if (viewModel.audience == Visibility.UNLISTED) {
+ Icon(
+ imageVector = Icons.Outlined.Check,
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.primary
+ )
+ }
+ })
+ DropdownMenuItem(
+ text = { Text(stringResource(Res.string.followers_only)) },
+ onClick = { viewModel.audience = Visibility.PRIVATE },
+ trailingIcon = {
+ if (viewModel.audience == Visibility.PRIVATE) {
+ Icon(
+ imageVector = Icons.Outlined.Check,
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.primary
+ )
+ }
+ })
}
- Text(text = buttonText)
- }
- DropdownMenu(
- expanded = expanded,
- onDismissRequest = { expanded = false }) {
- DropdownMenuItem(text = { Text(stringResource(Res.string.audience_public)) },
- onClick = { viewModel.audience = Visibility.PUBLIC },
- trailingIcon = {
- if (viewModel.audience == Visibility.PUBLIC) {
- Icon(
- imageVector = Icons.Outlined.Check,
- contentDescription = null,
- tint = MaterialTheme.colorScheme.primary
- )
- }
- })
- DropdownMenuItem(text = { Text(stringResource(Res.string.unlisted)) },
- onClick = { viewModel.audience = Visibility.UNLISTED },
- trailingIcon = {
- if (viewModel.audience == Visibility.UNLISTED) {
- Icon(
- imageVector = Icons.Outlined.Check,
- contentDescription = null,
- tint = MaterialTheme.colorScheme.primary
- )
- }
- })
- DropdownMenuItem(text = { Text(stringResource(Res.string.followers_only)) },
- onClick = { viewModel.audience = Visibility.PRIVATE },
- trailingIcon = {
- if (viewModel.audience == Visibility.PRIVATE) {
- Icon(
- imageVector = Icons.Outlined.Check,
- contentDescription = null,
- tint = MaterialTheme.colorScheme.primary
- )
- }
- })
- }
- }
- })
- TextFieldLocationsComposable(
- submit = { viewModel.setLocation(it) },
- submitPlace = {},
- initialValue = null,
- labelStringId = Res.string.location,
- modifier = Modifier.fillMaxWidth(),
- imeAction = ImeAction.Default,
- suggestionsBoxColor = MaterialTheme.colorScheme.surfaceContainer,
- submitButton = null
- )
+ }
+ })
+ TextFieldLocationsComposable(
+ submit = { viewModel.setLocation(it) },
+ submitPlace = {},
+ initialValue = null,
+ labelStringId = Res.string.location,
+ modifier = Modifier.fillMaxWidth(),
+ imeAction = ImeAction.Default,
+ suggestionsBoxColor = MaterialTheme.colorScheme.surfaceContainer,
+ submitButton = null
+ )
+ }
}
- }
- if (viewModel.addImageError.first.isNotBlank()) {
- AlertDialog(title = {
- Text(text = viewModel.addImageError.first)
- }, text = {
- Text(text = viewModel.addImageError.second)
- }, onDismissRequest = {
- viewModel.addImageError = Pair("", "")
- }, confirmButton = {
- TextButton(onClick = {
+ if (viewModel.addImageError.first.isNotBlank()) {
+ AlertDialog(title = {
+ Text(text = viewModel.addImageError.first)
+ }, text = {
+ Text(text = viewModel.addImageError.second)
+ }, onDismissRequest = {
viewModel.addImageError = Pair("", "")
- }) {
- Text("Ok")
- }
- })
- }
+ }, confirmButton = {
+ TextButton(onClick = {
+ viewModel.addImageError = Pair("", "")
+ }) {
+ Text("Ok")
+ }
+ })
+ }
- if (showReleaseAlert) {
- AlertDialog(title = {
- Text(text = "Are you sure?")
- }, onDismissRequest = {
- showReleaseAlert = false
- }, dismissButton = {
- TextButton(onClick = {
+ if (showReleaseAlert) {
+ AlertDialog(title = {
+ Text(text = "Are you sure?")
+ }, onDismissRequest = {
showReleaseAlert = false
- }) {
- Text(stringResource(Res.string.cancel))
- }
- }, confirmButton = {
- TextButton(onClick = {
- showReleaseAlert = false
- viewModel.post(navController)
- }) {
- Text(stringResource(Res.string.release))
- }
- })
- }
+ }, dismissButton = {
+ TextButton(onClick = {
+ showReleaseAlert = false
+ }) {
+ Text(stringResource(Res.string.cancel))
+ }
+ }, confirmButton = {
+ TextButton(onClick = {
+ showReleaseAlert = false
+ viewModel.post(navController)
+ }) {
+ Text(stringResource(Res.string.release))
+ }
+ })
+ }
- LoadingComposable(isLoading = viewModel.createPostState.isLoading)
- //LoadingComposable(isLoading = viewModel.mediaUploadState.isLoading)
- ErrorComposableDialog(
- errorMessage = viewModel.mediaUploadState.error,
- onDismiss = { viewModel.mediaUploadState = viewModel.mediaUploadState.copy(error = "") }
- )
+ LoadingComposable(isLoading = viewModel.createPostState.isLoading)
+ //LoadingComposable(isLoading = viewModel.mediaUploadState.isLoading)
+ ErrorComposableDialog(
+ errorMessage = viewModel.mediaUploadState.error, onDismiss = {
+ viewModel.mediaUploadState = viewModel.mediaUploadState.copy(error = "")
+ })
- ErrorComposableDialog(
- errorMessage = viewModel.createPostState.error,
- onDismiss = { viewModel.createPostState = viewModel.createPostState.copy(error = "") }
- )
+ ErrorComposableDialog(
+ errorMessage = viewModel.createPostState.error, onDismiss = {
+ viewModel.createPostState = viewModel.createPostState.copy(error = "")
+ })
+ }
}
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ text = stringResource(Res.string.new_post),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, actions = {
+ Button(
+ onClick = { showReleaseAlert = true },
+ enabled = (viewModel.images.isNotEmpty() && viewModel.images.none { it.isLoading })
+ ) {
+ Text(text = stringResource(Res.string.release))
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
}
@@ -324,8 +351,7 @@ fun ImagesPager(
Card(Modifier.fillMaxWidth().aspectRatio(1f).clickable { launcher.launch() }) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Icon(
- modifier = Modifier.height(50.dp)
- .width(50.dp),
+ modifier = Modifier.height(50.dp).width(50.dp),
imageVector = vectorResource(Res.drawable.add_outline),
contentDescription = null,
)
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/notifications/NotificationsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/notifications/NotificationsComposable.kt
index 91557215..0579cd8f 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/notifications/NotificationsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/notifications/NotificationsComposable.kt
@@ -1,5 +1,6 @@
package com.daniebeler.pfpixelix.ui.composables.notifications
+import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -24,7 +25,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Email
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -32,12 +32,15 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.domain.service.platform.PlatformFeatures
@@ -70,28 +73,37 @@ fun NotificationsComposable(
val scrollState = rememberScrollState()
Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(stringResource(Res.string.notifications), fontWeight = FontWeight.Bold)
- }, actions = {
- if (PlatformFeatures.notificationWidgets) {
- IconButton(onClick = {
- viewModel.pinWidget()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.extension_puzzle_outline),
- contentDescription = "add widget"
- )
+ TopAppBar(
+ title = {
+ Text(
+ stringResource(Res.string.notifications),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, actions = {
+ if (PlatformFeatures.notificationWidgets) {
+ IconButton(onClick = {
+ viewModel.pinWidget()
+ }) {
+ Icon(
+ imageVector = vectorResource(Res.drawable.extension_puzzle_outline),
+ contentDescription = "add widget"
+ )
+ }
}
- }
- })
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}) { paddingValues ->
Box(
- modifier = Modifier
- .fillMaxSize()
- .padding(paddingValues)
+ modifier = Modifier.fillMaxSize().padding(paddingValues)
) {
Column {
- Row(modifier = Modifier.horizontalScroll(scrollState)) {
+ Row(
+ modifier = Modifier.background(MaterialTheme.colorScheme.surfaceContainer)
+ .horizontalScroll(scrollState)
+ ) {
Spacer(modifier = Modifier.width(12.dp))
if (viewModel.filter == NotificationsFilterEnum.All) {
ActiveFilterButton(text = stringResource(Res.string.all))
@@ -107,8 +119,7 @@ fun NotificationsComposable(
ActiveFilterButton(text = stringResource(Res.string.followers))
} else {
InactiveFilterButton(
- text = stringResource(Res.string.followers),
- onClick = {
+ text = stringResource(Res.string.followers), onClick = {
viewModel.changeFilter(NotificationsFilterEnum.Followers)
})
}
@@ -142,9 +153,14 @@ fun NotificationsComposable(
viewModel.changeFilter(NotificationsFilterEnum.Mentions)
})
}
+
+ Spacer(modifier = Modifier.width(12.dp))
}
- Spacer(modifier = Modifier.height(12.dp))
+ Spacer(
+ modifier = Modifier.fillMaxWidth().height(12.dp)
+ .background(MaterialTheme.colorScheme.surfaceContainer)
+ )
PullToRefreshBox(
isRefreshing = viewModel.notificationsState.isRefreshing,
@@ -181,9 +197,7 @@ fun NotificationsComposable(
if (viewModel.notificationsState.isLoading && !viewModel.notificationsState.isRefreshing) {
item {
CircularProgressIndicator(
- modifier = Modifier
- .fillMaxWidth()
- .height(80.dp)
+ modifier = Modifier.fillMaxWidth().height(80.dp)
.wrapContentSize(Alignment.Center)
)
}
@@ -234,7 +248,7 @@ private fun InactiveFilterButton(text: String, onClick: () -> Unit) {
onClick = { onClick() },
shape = RoundedCornerShape(12.dp),
colors = ButtonDefaults.buttonColors(
- containerColor = MaterialTheme.colorScheme.surfaceContainer,
+ containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
contentColor = MaterialTheme.colorScheme.onSurface
)
) {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/post/PostComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/post/PostComposable.kt
index 0812eb7a..be6ad7e5 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/post/PostComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/post/PostComposable.kt
@@ -13,16 +13,13 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
@@ -77,7 +74,6 @@ import androidx.compose.ui.zIndex
import androidx.navigation.NavController
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
-import com.daniebeler.pfpixelix.di.LocalAppComponent
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.domain.model.MediaAttachment
import com.daniebeler.pfpixelix.domain.model.Post
@@ -110,14 +106,12 @@ import pixelix.app.generated.resources.heart
import pixelix.app.generated.resources.heart_outline
import pixelix.app.generated.resources.liked_by
import pixelix.app.generated.resources.media_description
-import pixelix.app.generated.resources.no_likes_yet
import pixelix.app.generated.resources.ok
import pixelix.app.generated.resources.others
import pixelix.app.generated.resources.reblogged_by
import pixelix.app.generated.resources.sync_outline
import pixelix.app.generated.resources.sync_outline_bold
import pixelix.app.generated.resources.this_action_cannot_be_undone
-import pixelix.app.generated.resources.view_comments
@OptIn(ExperimentalMaterial3Api::class)
@@ -202,22 +196,30 @@ fun PostComposable(
})
if (viewModel.post != null) {
- Column(modifier = modifier) {
-
+ Column(
+ modifier = modifier.clip(
+ RoundedCornerShape(16.dp)
+ ).background(MaterialTheme.colorScheme.surfaceContainerLow)
+ .padding(top = 12.dp, bottom = 12.dp)
+ ) {
post.rebloggedBy?.let { reblogAccount ->
Row(
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(8.dp),
+ horizontalArrangement = Arrangement.spacedBy(6.dp),
modifier = Modifier.padding(start = 16.dp, end = 12.dp).clickable(onClick = {
navController.navigate(Destination.Profile(reblogAccount.id))
})
) {
- Icon(Icons.Outlined.Cached, contentDescription = "reblogged by")
+ Icon(
+ Icons.Outlined.Cached,
+ contentDescription = "reblogged by",
+ modifier = Modifier.size(20.dp)
+ )
Text(
stringResource(
Res.string.reblogged_by,
reblogAccount.displayname ?: reblogAccount.username
- ), fontSize = 12.sp
+ ), fontSize = 11.sp
)
}
}
@@ -232,18 +234,21 @@ fun PostComposable(
model = viewModel.post!!.account.avatar,
error = painterResource(Res.drawable.default_avatar),
contentDescription = "",
- modifier = Modifier.height(36.dp).width(36.dp).clip(CircleShape)
+ modifier = Modifier.height(40.dp).width(40.dp).clip(CircleShape)
)
Column(modifier = Modifier.padding(start = 8.dp)) {
-// Text(
-// text = viewModel.post!!.account.displayname ?: "",
-// fontWeight = FontWeight.Bold,
-// lineHeight = 10.sp
-// )
Text(
text = viewModel.post!!.account.acct,
fontSize = 14.sp,
- fontWeight = FontWeight.Bold
+ fontWeight = FontWeight.Bold,
+ lineHeight = 8.sp
+ )
+
+ Text(
+ text = timeAgoText.value,
+ fontSize = 12.sp,
+ lineHeight = 8.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
)
if (viewModel.post!!.place != null) {
@@ -273,6 +278,7 @@ fun PostComposable(
}) {
Icon(
imageVector = vectorResource(Res.drawable.ellipsis_vertical),
+ modifier = Modifier.size(20.dp),
contentDescription = ""
)
}
@@ -283,7 +289,9 @@ fun PostComposable(
if (viewModel.post!!.mediaAttachments.isNotEmpty()) {
if (viewModel.post!!.sensitive && !viewModel.showPost && viewModel.blurSensitiveContent) {
- Box(modifier.padding(start = 12.dp, end = 12.dp).clip(RoundedCornerShape(16.dp))) {
+ Box(
+ modifier.padding(start = 8.dp, end = 8.dp).clip(RoundedCornerShape(16.dp))
+ ) {
val blurHashBitmap = BlurHashDecoder.decode(
viewModel.post!!.mediaAttachments[0].blurHash
)
@@ -327,8 +335,9 @@ fun PostComposable(
} else {
if (viewModel.post!!.mediaAttachments.count() > 1) {
- val smallestAspectRatio = viewModel.post!!.mediaAttachments
- .minByOrNull { it.meta?.original?.aspect ?: 1.0 }
+ val smallestAspectRatio = viewModel.post!!.mediaAttachments.minByOrNull {
+ it.meta?.original?.aspect ?: 1.0
+ }
Box {
HorizontalPager(
state = pagerState, modifier = Modifier.zIndex(50f).aspectRatio(
@@ -337,7 +346,7 @@ fun PostComposable(
) { page ->
Box(
modifier = Modifier.zIndex(10f)
- .padding(start = 12.dp, end = 12.dp)
+ .padding(start = 8.dp, end = 8.dp)
) {
PostImage(
mediaAttachment = viewModel.post!!.mediaAttachments[page],
@@ -352,13 +361,13 @@ fun PostComposable(
Box(
modifier = Modifier.align(Alignment.TopEnd).zIndex(51f)
- .padding(top = 16.dp, end = 28.dp).clip(CircleShape)
+ .padding(top = 20.dp, end = 20.dp).clip(CircleShape)
.background(MaterialTheme.colorScheme.background.copy(alpha = 0.5f))
- .padding(vertical = 3.dp, horizontal = 12.dp)
+ .padding(vertical = 2.dp, horizontal = 8.dp)
) {
Text(
text = (pagerState.currentPage + 1).toString() + "/" + viewModel.post!!.mediaAttachments.count(),
- fontSize = 14.sp
+ fontSize = 13.sp
)
}
}
@@ -366,7 +375,7 @@ fun PostComposable(
Spacer(modifier = Modifier.height(5.dp))
Row(
Modifier.wrapContentHeight().fillMaxWidth()
- .align(Alignment.CenterHorizontally).padding(bottom = 8.dp),
+ .align(Alignment.CenterHorizontally),
horizontalArrangement = Arrangement.Center
) {
repeat(pagerState.pageCount) { iteration ->
@@ -417,63 +426,78 @@ fun PostComposable(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.clip(
+ RoundedCornerShape(percent = 50)
+ ).background(MaterialTheme.colorScheme.surfaceContainerHigh)
+ .padding(horizontal = 10.dp, vertical = 4.dp)
+ ) {
+ if (viewModel.post!!.favourited) {
+ Icon(
+ imageVector = vectorResource(Res.drawable.heart),
+ modifier = Modifier.size(22.dp).clickable {
+ viewModel.unlikePost(postId, updatePost)
+ }.scale(heartScale),
+ contentDescription = "unlike post",
+ tint = Color(0xFFDD2E44)
+ )
+ } else {
+ Icon(
+ imageVector = vectorResource(Res.drawable.heart_outline),
+ modifier = Modifier.size(22.dp).clickable {
+ animateHeart = true
+ viewModel.likePost(postId, updatePost)
+ },
+ contentDescription = "like post"
+ )
- Row(verticalAlignment = Alignment.CenterVertically) {
- if (viewModel.post!!.favourited) {
- Icon(
- imageVector = vectorResource(Res.drawable.heart),
- modifier = Modifier.size(24.dp).clickable {
- viewModel.unlikePost(postId, updatePost)
- }.scale(heartScale),
- contentDescription = "unlike post",
- tint = Color(0xFFDD2E44)
- )
- } else {
- Icon(
- imageVector = vectorResource(Res.drawable.heart_outline),
- modifier = Modifier.size(24.dp).clickable {
- animateHeart = true
- viewModel.likePost(postId, updatePost)
- },
- contentDescription = "like post"
- )
-
- }
-
- Spacer(Modifier.width(4.dp))
+ }
- Text(
- text = viewModel.post!!.favouritesCount.toString(),
- fontSize = 16.sp,
- fontWeight = FontWeight.Bold
- )
+ Spacer(Modifier.width(4.dp))
- Spacer(Modifier.width(32.dp))
+ Text(
+ text = viewModel.post!!.favouritesCount.toString(),
+ fontSize = 16.sp,
+ fontWeight = FontWeight.Bold
+ )
+ }
- Icon(
- imageVector = vectorResource(Res.drawable.chatbubble_outline),
- modifier = Modifier.size(24.dp).clickable {
- viewModel.loadReplies(
- postId
- )
- showBottomSheet = 1
- },
- contentDescription = "comments of post"
- )
- Spacer(Modifier.width(4.dp))
+ Spacer(Modifier.width(16.dp))
- Text(
- text = viewModel.post!!.replyCount.toString(),
- fontSize = 16.sp,
- fontWeight = FontWeight.Bold
- )
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.clip(
+ RoundedCornerShape(percent = 50)
+ ).background(MaterialTheme.colorScheme.surfaceContainerHigh)
+ .padding(horizontal = 10.dp, vertical = 4.dp)
+ ) {
+ Icon(
+ imageVector = vectorResource(Res.drawable.chatbubble_outline),
+ modifier = Modifier.size(22.dp).clickable {
+ viewModel.loadReplies(
+ postId
+ )
+ showBottomSheet = 1
+ },
+ contentDescription = "comments of post"
+ )
+ Spacer(Modifier.width(4.dp))
+ Text(
+ text = viewModel.post!!.replyCount.toString(),
+ fontSize = 16.sp,
+ fontWeight = FontWeight.Bold
+ )
+ }
}
Row {
-
if (viewModel.post!!.reblogged) {
IconButton(onClick = {
viewModel.unreblogPost(postId, updatePost)
@@ -549,10 +573,6 @@ fun PostComposable(
showBottomSheet = 3
})
}
- } else {
- Text(
- text = stringResource(Res.string.no_likes_yet), fontSize = 14.sp
- )
}
}
@@ -569,29 +589,6 @@ fun PostComposable(
)
}
}
-
- if (viewModel.post!!.replyCount > 0 && showReplies) {
-
- Spacer(modifier = Modifier.height(6.dp))
-
- Text(
- text = stringResource(
- Res.string.view_comments, viewModel.post!!.replyCount
- ),
- color = MaterialTheme.colorScheme.onSurfaceVariant,
- modifier = Modifier.clickable {
- viewModel.loadReplies(
- postId
- )
- showBottomSheet = 1
- })
- }
-
- Text(
- text = timeAgoText.value,
- fontSize = 12.sp,
- color = MaterialTheme.colorScheme.onSurfaceVariant
- )
}
}
@@ -604,8 +601,7 @@ fun PostComposable(
ModalBottomSheet(
onDismissRequest = {
showBottomSheet = 0
- },
- sheetState = sheetState
+ }, sheetState = sheetState
) {
if (showBottomSheet == 1) {
CommentsBottomSheet(post, navController, viewModel)
@@ -618,8 +614,7 @@ fun PostComposable(
post,
pagerState.currentPage,
navController,
- { showBottomSheet = 0 }
- )
+ { showBottomSheet = 0 })
} else {
ShareBottomSheet(
post.url,
@@ -628,8 +623,7 @@ fun PostComposable(
post,
pagerState.currentPage,
navController,
- { showBottomSheet = 0 }
- )
+ { showBottomSheet = 0 })
}
} else if (showBottomSheet == 3) {
LikesBottomSheet(viewModel, navController)
@@ -844,8 +838,7 @@ fun MediaDialog(
Box(
modifier = Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.8f)).clickable {
closeDialog()
- },
- contentAlignment = Alignment.Center
+ }, contentAlignment = Alignment.Center
) {
Box(modifier = Modifier.zIndex(2f).zoomable(zoomState).clickable { }) {
if (mediaAttachment.type != "video") {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/CollectionsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/CollectionsComposable.kt
index 615c5109..0276d1c1 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/CollectionsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/CollectionsComposable.kt
@@ -116,7 +116,7 @@ fun CollectionsComposable(
.height(84.dp)
.width(84.dp)
.clip(CircleShape)
- .background(MaterialTheme.colorScheme.surfaceContainer),
+ .background(MaterialTheme.colorScheme.surfaceContainerHigh),
contentAlignment = Alignment.Center
) {
Icon(
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/PostsWrapperComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/PostsWrapperComposable.kt
index 9cb3b296..123f93d4 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/PostsWrapperComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/PostsWrapperComposable.kt
@@ -96,7 +96,7 @@ private fun LazyListScope.PostsGridInScope(
item {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
- modifier = Modifier.padding(horizontal = 12.dp)
+ modifier = Modifier.padding(horizontal = 4.dp)
) {
Box(modifier = Modifier.fillMaxWidth(1.99f / 3f)) {
CustomPost(
@@ -133,7 +133,7 @@ private fun LazyListScope.PostsGridInScope(
val rows = posts.takeLast(posts.size - 3).chunked(3)
itemsIndexed(rows) { rowIndex, rowItems ->
Row(
- modifier = Modifier.fillMaxWidth().padding(horizontal = 10.dp),
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 2.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
// Fill the row with 3 items (or fewer for the last row)
@@ -268,7 +268,7 @@ private fun LazyListScope.PostsListInScope(
updatePost: (post: Post) -> Unit,
navController: NavController
) {
- val spacedBy: Dp = 28.dp
+ val spacedBy: Dp = 24.dp
if (posts.isNotEmpty()) {
@@ -278,7 +278,7 @@ private fun LazyListScope.PostsListInScope(
val zIndex = remember {
mutableFloatStateOf(1f)
}
- Box(modifier = Modifier.zIndex(zIndex.floatValue)) {
+ Box(modifier = Modifier.zIndex(zIndex.floatValue).padding(horizontal = 8.dp)) {
PostComposable(post = item,
postGetsDeleted = postGetsDeleted,
navController = navController,
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/ProfileTopSection.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/ProfileTopSection.kt
index 38f9ce20..4144a01a 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/ProfileTopSection.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/ProfileTopSection.kt
@@ -60,16 +60,13 @@ fun ProfileTopSection(
openUrl: (url: String) -> Unit
) {
if (account != null) {
- Column(Modifier.padding(12.dp)) {
+ Column(Modifier.padding(12.dp).fillMaxWidth()) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(
model = account.avatar,
error = painterResource(Res.drawable.default_avatar),
contentDescription = "",
- modifier = Modifier
- .height(76.dp)
- .width(76.dp)
- .clip(CircleShape)
+ modifier = Modifier.height(76.dp).width(76.dp).clip(CircleShape)
)
Row(
@@ -82,10 +79,14 @@ fun ProfileTopSection(
fontWeight = FontWeight.Bold,
fontSize = 18.sp
)
- Text(text = pluralStringResource(Res.plurals.posts, account.postsCount), fontSize = 12.sp)
+ Text(
+ text = pluralStringResource(Res.plurals.posts, account.postsCount),
+ fontSize = 12.sp
+ )
}
- Column(horizontalAlignment = Alignment.CenterHorizontally,
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.clickable {
navController.navigate(Destination.Followers(account.id, true))
}) {
@@ -94,10 +95,15 @@ fun ProfileTopSection(
fontWeight = FontWeight.Bold,
fontSize = 18.sp
)
- Text(text = pluralStringResource(Res.plurals.follower, account.followersCount), fontSize = 12.sp)
+ Text(
+ text = pluralStringResource(
+ Res.plurals.follower, account.followersCount
+ ), fontSize = 12.sp
+ )
}
- Column(horizontalAlignment = Alignment.CenterHorizontally,
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.clickable {
navController.navigate(Destination.Followers(account.id, false))
}) {
@@ -106,7 +112,11 @@ fun ProfileTopSection(
fontWeight = FontWeight.Bold,
fontSize = 18.sp
)
- Text(text = pluralStringResource(Res.plurals.following, account.followingCount), fontSize = 12.sp)
+ Text(
+ text = pluralStringResource(
+ Res.plurals.following, account.followingCount
+ ), fontSize = 12.sp
+ )
}
}
}
@@ -164,20 +174,22 @@ fun ProfileTopSection(
Spacer(modifier = Modifier.height(12.dp))
if (account.note.isNotBlank()) {
- HashtagsMentionsTextView(text = account.note,
+ HashtagsMentionsTextView(
+ text = account.note,
+ textSize = 14.sp,
mentions = null,
navController = navController,
openUrl = { url -> openUrl(url) })
}
- account.website?.let {
+ if (account.website.isNotBlank()) {
Row(Modifier.padding(top = 12.dp), verticalAlignment = Alignment.CenterVertically) {
Text(
- text = account.website.toString().substringAfter("https://"),
+ text = account.website.substringAfter("https://"),
color = MaterialTheme.colorScheme.primary,
fontWeight = FontWeight.Bold,
- modifier = Modifier.clickable(onClick = { openUrl(account.website.toString()) })
+ modifier = Modifier.clickable(onClick = { openUrl(account.website) })
)
}
}
@@ -193,11 +205,8 @@ fun ProfileTopSection(
}
Text(
text = stringResource(
- Res.string.joined_date,
- formatter.format(date)
- ),
- color = MaterialTheme.colorScheme.onSurfaceVariant,
- fontSize = 10.sp
+ Res.string.joined_date, formatter.format(date)
+ ), color = MaterialTheme.colorScheme.onSurfaceVariant, fontSize = 10.sp
)
}
}
@@ -207,11 +216,9 @@ fun ProfileTopSection(
@Composable
private fun ProfileBadge(text: String, color: Color = MaterialTheme.colorScheme.onSurfaceVariant) {
Box(
- Modifier
- .border(
+ Modifier.border(
BorderStroke(1.dp, color), shape = RoundedCornerShape(8.dp)
- )
- .padding(horizontal = 6.dp)
+ ).padding(horizontal = 6.dp)
) {
Text(text = text, fontSize = 9.sp, color = color)
}
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/SwitchViewComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/SwitchViewComposable.kt
index 7c8cfc44..4c2452cb 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/SwitchViewComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/SwitchViewComposable.kt
@@ -1,5 +1,6 @@
package com.daniebeler.pfpixelix.ui.composables.profile
+import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -10,6 +11,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/other_profile/OtherProfileComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/other_profile/OtherProfileComposable.kt
index 5f495f86..8d219980 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/other_profile/OtherProfileComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/other_profile/OtherProfileComposable.kt
@@ -1,32 +1,32 @@
package com.daniebeler.pfpixelix.ui.composables.profile.other_profile
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.Photo
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
@@ -34,9 +34,10 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
@@ -46,7 +47,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
-import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
@@ -70,7 +70,6 @@ import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
import com.daniebeler.pfpixelix.ui.navigation.Destination
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.block
import pixelix.app.generated.resources.block_account
@@ -87,7 +86,6 @@ import pixelix.app.generated.resources.block_consequence_9
import pixelix.app.generated.resources.block_this_profile
import pixelix.app.generated.resources.browsers_outline
import pixelix.app.generated.resources.cancel
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.default_avatar
import pixelix.app.generated.resources.follow
import pixelix.app.generated.resources.message
@@ -111,8 +109,8 @@ import pixelix.app.generated.resources.unmute_account
import pixelix.app.generated.resources.unmute_caps
import pixelix.app.generated.resources.unmute_this_profile
-@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class,
- ExperimentalComposeUiApi::class
+@OptIn(
+ ExperimentalMaterial3Api::class
)
@Composable
fun OtherProfileComposable(
@@ -139,197 +137,206 @@ fun OtherProfileComposable(
}
}
+ Box(modifier = Modifier.fillMaxSize()) {
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Row {
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
- Text(
- text = viewModel.accountState.account?.username ?: "",
- fontWeight = FontWeight.Bold
- )
- Text(
- text = viewModel.domain, fontSize = 12.sp, lineHeight = 6.sp
- )
- }
-
- }
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- }, actions = {
-
- if (viewModel.domain.isNotEmpty()) {
- DomainSoftwareComposable(
- domain = viewModel.domain
- )
- }
-
- IconButton(onClick = {
- showBottomSheet = true
- }) {
- Icon(
- imageVector = Icons.Outlined.MoreVert, contentDescription = ""
- )
- }
- })
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- }) { paddingValues ->
- PullToRefreshBox (
- isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
- onRefresh = { viewModel.loadData(userId, true, navController) },
- modifier = Modifier
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
.fillMaxSize()
- .padding(paddingValues)
) {
-
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(4.dp),
- state = lazyGridState
+ PullToRefreshBox(
+ isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
+ onRefresh = { viewModel.loadData(userId, true, navController) },
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
- item {
- Column {
- if (viewModel.accountState.account != null) {
- ProfileTopSection(account = viewModel.accountState.account,
- relationship = viewModel.relationshipState.accountRelationship,
- navController,
- openUrl = { url ->
- viewModel.openUrl(url)
- })
- }
-
- MutualFollowersComposable(
- mutualFollowersState = viewModel.mutualFollowersState,
- navController = navController
- )
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 12.dp)
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(4.dp), state = lazyGridState
+ ) {
+ item {
+ Column(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ).background(MaterialTheme.colorScheme.surfaceContainer)
+ .padding(top = 24.dp, bottom = 12.dp)
) {
- var containerColor by remember {
- mutableStateOf(Color(0xFFFFFFFF))
+ if (viewModel.accountState.account != null) {
+ ProfileTopSection(
+ account = viewModel.accountState.account,
+ relationship = viewModel.relationshipState.accountRelationship,
+ navController,
+ openUrl = { url ->
+ viewModel.openUrl(url)
+ })
}
- var contentColor by remember {
- mutableStateOf(Color(0xFFFFFFFF))
- }
+ MutualFollowersComposable(
+ mutualFollowersState = viewModel.mutualFollowersState,
+ navController = navController
+ )
- if (viewModel.relationshipState.accountRelationship?.following == true) {
- containerColor = MaterialTheme.colorScheme.secondaryContainer
- contentColor = MaterialTheme.colorScheme.onSecondaryContainer
- } else {
- containerColor = MaterialTheme.colorScheme.primary
- contentColor = MaterialTheme.colorScheme.onPrimary
- }
+ Row(
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp)
+ ) {
+ var containerColor by remember {
+ mutableStateOf(Color(0xFFFFFFFF))
+ }
- Button(
- onClick = {
- if (!viewModel.relationshipState.isLoading && viewModel.relationshipState.accountRelationship != null) {
- if (viewModel.relationshipState.accountRelationship?.following == true) {
- viewModel.unfollowAccount(viewModel.userId)
- } else {
- viewModel.followAccount(viewModel.userId)
+ var contentColor by remember {
+ mutableStateOf(Color(0xFFFFFFFF))
+ }
+
+ if (viewModel.relationshipState.accountRelationship?.following == true) {
+ containerColor = MaterialTheme.colorScheme.secondaryContainer
+ contentColor = MaterialTheme.colorScheme.onSecondaryContainer
+ } else {
+ containerColor = MaterialTheme.colorScheme.primary
+ contentColor = MaterialTheme.colorScheme.onPrimary
+ }
+
+ Button(
+ onClick = {
+ if (!viewModel.relationshipState.isLoading && viewModel.relationshipState.accountRelationship != null) {
+ if (viewModel.relationshipState.accountRelationship?.following == true) {
+ viewModel.unfollowAccount(viewModel.userId)
+ } else {
+ viewModel.followAccount(viewModel.userId)
+ }
}
- }
- },
- modifier = Modifier.weight(1f),
- shape = RoundedCornerShape(12.dp),
- contentPadding = PaddingValues(12.dp),
- colors = ButtonDefaults.buttonColors(
- containerColor = containerColor, contentColor = contentColor
- )
- ) {
- if (viewModel.relationshipState.isLoading) {
- CircularProgressIndicator(
- modifier = Modifier.size(20.dp), color = contentColor
+ },
+ modifier = Modifier.weight(1f),
+ shape = RoundedCornerShape(12.dp),
+ contentPadding = PaddingValues(12.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = containerColor, contentColor = contentColor
)
- } else {
- if (viewModel.relationshipState.accountRelationship?.following == true) {
- Text(text = stringResource(Res.string.unfollow))
+ ) {
+ if (viewModel.relationshipState.isLoading) {
+ CircularProgressIndicator(
+ modifier = Modifier.size(20.dp), color = contentColor
+ )
} else {
- Text(text = stringResource(Res.string.follow))
+ if (viewModel.relationshipState.accountRelationship?.following == true) {
+ Text(text = stringResource(Res.string.unfollow))
+ } else {
+ Text(text = stringResource(Res.string.follow))
+ }
}
}
- }
- Spacer(modifier = Modifier.width(12.dp))
+ Spacer(modifier = Modifier.width(12.dp))
- Button(
- onClick = {
- viewModel.accountState.account?.let { account ->
- navController.navigate(Destination.Chat(account.id))
- }
- },
- modifier = Modifier.weight(1f),
- shape = RoundedCornerShape(12.dp),
- contentPadding = PaddingValues(12.dp),
- colors = ButtonDefaults.buttonColors(
- containerColor = MaterialTheme.colorScheme.surfaceContainer,
- contentColor = MaterialTheme.colorScheme.onSecondaryContainer
- )
- ) {
- Text(text = stringResource(Res.string.message))
+ Button(
+ onClick = {
+ viewModel.accountState.account?.let { account ->
+ navController.navigate(Destination.Chat(account.id))
+ }
+ },
+ modifier = Modifier.weight(1f),
+ shape = RoundedCornerShape(12.dp),
+ contentPadding = PaddingValues(12.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
+ contentColor = MaterialTheme.colorScheme.onSurface
+ )
+ ) {
+ Text(text = stringResource(Res.string.message))
+ }
}
- }
- viewModel.accountState.account?.let { account ->
- CollectionsComposable(collectionsState = viewModel.collectionsState,
- getMoreCollections = {viewModel.getCollections(account.id, true)},
- navController = navController,
- instanceDomain = viewModel.domain,
- openUrl = { url -> viewModel.openUrl(url) })
+ viewModel.accountState.account?.let { account ->
+ CollectionsComposable(
+ collectionsState = viewModel.collectionsState,
+ getMoreCollections = {
+ viewModel.getCollections(
+ account.id, true
+ )
+ },
+ navController = navController,
+ instanceDomain = viewModel.domain,
+ openUrl = { url -> viewModel.openUrl(url) })
+ }
}
+ }
- HorizontalDivider(Modifier.padding(bottom = 12.dp, top = 12.dp))
-
- SwitchViewComposable(postsCount = viewModel.accountState.account?.postsCount
- ?: 0,
+ item {
+ SwitchViewComposable(
+ postsCount = viewModel.accountState.account?.postsCount ?: 0,
viewType = viewModel.view,
onViewChange = {
viewModel.changeView(it)
})
}
- }
- PostsWrapperComposable(
- posts = viewModel.postsState.posts,
- isLoading = viewModel.postsState.isLoading,
- isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
- error = viewModel.postsState.error,
- endReached = viewModel.postsState.endReached,
- emptyMessage = EmptyState(
- icon = Icons.Outlined.Photo, heading = "No Posts"
- ),
- view = viewModel.view,
- isFirstImageLarge = true,
- postGetsDeleted = { viewModel.postGetsDeleted(it) },
- updatePost = { viewModel.updatePost(it) },
- navController = navController
- )
-
- /*PostsWrapperComposable(
- accountState = viewModel.accountState,
- postsState = viewModel.postsState,
- navController = navController,
- emptyState = EmptyState(
- icon = Icons.Outlined.Photo, heading = "No Posts"
- ),
- view = viewModel.view,
- postGetsDeleted = { viewModel.postGetsDeleted(it) },
- isFirstImageLarge = true
- )*/
+ PostsWrapperComposable(
+ posts = viewModel.postsState.posts,
+ isLoading = viewModel.postsState.isLoading,
+ isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
+ error = viewModel.postsState.error,
+ endReached = viewModel.postsState.endReached,
+ emptyMessage = EmptyState(
+ icon = Icons.Outlined.Photo, heading = "No Posts"
+ ),
+ view = viewModel.view,
+ isFirstImageLarge = true,
+ postGetsDeleted = { viewModel.postGetsDeleted(it) },
+ updatePost = { viewModel.updatePost(it) },
+ navController = navController
+ )
+ }
}
+
}
+
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Row {
+ Column {
+ Text(
+ text = viewModel.accountState.account?.username ?: "",
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ Text(
+ text = viewModel.domain, fontSize = 12.sp, lineHeight = 6.sp
+ )
+ }
+
+ }
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, actions = {
+
+ if (viewModel.domain.isNotEmpty()) {
+ DomainSoftwareComposable(
+ domain = viewModel.domain
+ )
+ }
+
+ IconButton(onClick = {
+ showBottomSheet = true
+ }) {
+ Icon(
+ imageVector = Icons.Outlined.MoreVert, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
- ToTopButton(listState = lazyGridState, refresh = {viewModel.loadData(userId, true, navController)})
+ ToTopButton(
+ listState = lazyGridState, refresh = { viewModel.loadData(userId, true, navController) })
InfiniteListHandler(lazyListState = lazyGridState) {
viewModel.getPostsPaginated(viewModel.userId)
@@ -346,47 +353,49 @@ fun OtherProfileComposable(
) {
if (viewModel.relationshipState.accountRelationship != null) {
if (viewModel.relationshipState.accountRelationship!!.muting) {
- ButtonRowElement(icon = Res.drawable.remove_circle_outline,
- text = stringResource(
+ ButtonRowElement(
+ icon = Res.drawable.remove_circle_outline, text = stringResource(
Res.string.unmute_this_profile
- ),
- onClick = {
+ ), onClick = {
showUnMuteAlert = true
})
} else {
- ButtonRowElement(icon = Res.drawable.remove_circle_outline,
- text = stringResource(
+ ButtonRowElement(
+ icon = Res.drawable.remove_circle_outline, text = stringResource(
Res.string.mute_this_profile
- ),
- onClick = {
+ ), onClick = {
showMuteAlert = true
})
}
if (viewModel.relationshipState.accountRelationship!!.blocking) {
- ButtonRowElement(icon = Res.drawable.remove_circle_outline, text = stringResource(
- Res.string.unblock_this_profile
- ), onClick = {
- showUnBlockAlert = true
- })
+ ButtonRowElement(
+ icon = Res.drawable.remove_circle_outline, text = stringResource(
+ Res.string.unblock_this_profile
+ ), onClick = {
+ showUnBlockAlert = true
+ })
} else {
- ButtonRowElement(icon = Res.drawable.remove_circle_outline, text = stringResource(
- Res.string.block_this_profile
- ), onClick = {
- showBlockAlert = true
- })
+ ButtonRowElement(
+ icon = Res.drawable.remove_circle_outline, text = stringResource(
+ Res.string.block_this_profile
+ ), onClick = {
+ showBlockAlert = true
+ })
}
}
HorizontalDivider(Modifier.padding(12.dp))
- ButtonRowElement(icon = Res.drawable.browsers_outline, text = stringResource(
- Res.string.open_in_browser
- ), onClick = {
- viewModel.openUrl(viewModel.accountState.account!!.url)
- })
+ ButtonRowElement(
+ icon = Res.drawable.browsers_outline, text = stringResource(
+ Res.string.open_in_browser
+ ), onClick = {
+ viewModel.openUrl(viewModel.accountState.account!!.url)
+ })
- ButtonRowElement(icon = Res.drawable.share_social_outline,
+ ButtonRowElement(
+ icon = Res.drawable.share_social_outline,
text = stringResource(Res.string.share_this_profile),
onClick = {
viewModel.shareAccountUrl()
@@ -396,31 +405,35 @@ fun OtherProfileComposable(
}
if (showUnMuteAlert) {
- UnMuteAccountAlert(onDismissRequest = { showUnMuteAlert = false }, onConfirmation = {
- showUnMuteAlert = false
- viewModel.unMuteAccount(viewModel.userId)
- }, account = viewModel.accountState.account!!
+ UnMuteAccountAlert(
+ onDismissRequest = { showUnMuteAlert = false }, onConfirmation = {
+ showUnMuteAlert = false
+ viewModel.unMuteAccount(viewModel.userId)
+ }, account = viewModel.accountState.account!!
)
}
if (showMuteAlert) {
- MuteAccountAlert(onDismissRequest = { showMuteAlert = false }, onConfirmation = {
- showMuteAlert = false
- viewModel.muteAccount(viewModel.userId)
- }, account = viewModel.accountState.account!!
+ MuteAccountAlert(
+ onDismissRequest = { showMuteAlert = false }, onConfirmation = {
+ showMuteAlert = false
+ viewModel.muteAccount(viewModel.userId)
+ }, account = viewModel.accountState.account!!
)
}
if (showBlockAlert) {
- BlockAccountAlert(onDismissRequest = { showBlockAlert = false }, onConfirmation = {
- showBlockAlert = false
- viewModel.blockAccount(viewModel.userId)
- }, account = viewModel.accountState.account!!
+ BlockAccountAlert(
+ onDismissRequest = { showBlockAlert = false }, onConfirmation = {
+ showBlockAlert = false
+ viewModel.blockAccount(viewModel.userId)
+ }, account = viewModel.accountState.account!!
)
}
if (showUnBlockAlert) {
- UnBlockAccountAlert(onDismissRequest = { showUnBlockAlert = false }, onConfirmation = {
- showUnBlockAlert = false
- viewModel.unblockAccount(viewModel.userId)
- }, account = viewModel.accountState.account!!
+ UnBlockAccountAlert(
+ onDismissRequest = { showUnBlockAlert = false }, onConfirmation = {
+ showUnBlockAlert = false
+ viewModel.unblockAccount(viewModel.userId)
+ }, account = viewModel.accountState.account!!
)
}
}
@@ -574,10 +587,7 @@ fun AlertTopSection(account: Account) {
model = account.avatar,
error = painterResource(Res.drawable.default_avatar),
contentDescription = "",
- modifier = Modifier
- .height(46.dp)
- .width(46.dp)
- .clip(CircleShape)
+ modifier = Modifier.height(46.dp).width(46.dp).clip(CircleShape)
)
Spacer(modifier = Modifier.width(10.dp))
Column {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/own_profile/OwnProfileComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/own_profile/OwnProfileComposable.kt
index 3fa0b30b..e5f848f9 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/own_profile/OwnProfileComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/profile/own_profile/OwnProfileComposable.kt
@@ -1,17 +1,18 @@
package com.daniebeler.pfpixelix.ui.composables.profile.own_profile
+import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -20,15 +21,14 @@ import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.Photo
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
@@ -37,13 +37,12 @@ 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.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
-import com.daniebeler.pfpixelix.di.LocalAppComponent
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.domain.service.platform.PlatformFeatures
import com.daniebeler.pfpixelix.ui.composables.InfiniteListHandler
@@ -71,138 +70,137 @@ fun OwnProfileComposable(
val lazyGridState = rememberLazyListState()
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Row(Modifier.clickable { showBottomSheet = 2 }) {
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
- Text(
- text = viewModel.accountState.account?.username ?: "",
- fontWeight = FontWeight.Bold
- )
- Text(
- text = viewModel.ownDomain, fontSize = 12.sp, lineHeight = 6.sp
- )
- }
- }
- }, actions = {
- if (viewModel.ownDomain.isNotEmpty()) {
- DomainSoftwareComposable(
- domain = viewModel.ownDomain
- )
- }
-
- IconButton(onClick = {
- showBottomSheet = 1
- }) {
- Icon(
- imageVector = Icons.Outlined.MoreVert, contentDescription = "preferences"
- )
- }
- })
+ Box(modifier = Modifier.fillMaxSize()) {
- }
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- ) { paddingValues ->
- PullToRefreshBox(
- isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
- onRefresh = { viewModel.loadData(true) },
- modifier = Modifier
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
.fillMaxSize()
- .padding(paddingValues)
) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(4.dp),
- state = lazyGridState
+ PullToRefreshBox(
+ isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
+ onRefresh = { viewModel.loadData(true) },
+ modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
) {
- item {
- Column {
- if (viewModel.accountState.account != null) {
- ProfileTopSection(account = viewModel.accountState.account,
- relationship = null,
- navController,
- openUrl = { url -> viewModel.openUrl(url) }
- )
-
- Row(
- Modifier
- .fillMaxWidth()
- .padding(horizontal = 12.dp)
- ) {
- Button(
- onClick = {
- navController.navigate(Destination.EditProfile)
- },
- modifier = Modifier.fillMaxWidth(),
- shape = RoundedCornerShape(12.dp),
- contentPadding = PaddingValues(12.dp),
- colors = ButtonDefaults.buttonColors(
- containerColor = MaterialTheme.colorScheme.surfaceContainer,
- contentColor = MaterialTheme.colorScheme.onSurface
- )
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(4.dp),
+ state = lazyGridState,
+ ) {
+ item {
+ Column(
+ modifier = Modifier.fillMaxWidth().clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ).background(MaterialTheme.colorScheme.surfaceContainer)
+ .padding(top = 24.dp, bottom = 12.dp)
+ ) {
+ if (viewModel.accountState.account != null) {
+ ProfileTopSection(
+ account = viewModel.accountState.account,
+ relationship = null,
+ navController,
+ openUrl = { url -> viewModel.openUrl(url) })
+
+ Row(
+ Modifier.fillMaxWidth().padding(horizontal = 12.dp)
) {
- Text(text = stringResource(Res.string.edit_profile))
+ Button(
+ onClick = {
+ navController.navigate(Destination.EditProfile)
+ },
+ modifier = Modifier.fillMaxWidth(),
+ shape = RoundedCornerShape(12.dp),
+ contentPadding = PaddingValues(12.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
+ contentColor = MaterialTheme.colorScheme.onSurface
+ )
+ ) {
+ Text(text = stringResource(Res.string.edit_profile))
+ }
}
}
- }
- CollectionsComposable(
- collectionsState = viewModel.collectionsState,
- getMoreCollections = {
- viewModel.accountState.account?.let {
- viewModel.getCollections(
- it.id,
- true
- )
- }
- },
- navController = navController,
- addNewButton = PlatformFeatures.addCollection,
- instanceDomain = viewModel.ownDomain,
- ) { url -> viewModel.openUrl(url) }
-
- HorizontalDivider(Modifier.padding(bottom = 12.dp, top = 12.dp))
+ CollectionsComposable(
+ collectionsState = viewModel.collectionsState,
+ getMoreCollections = {
+ viewModel.accountState.account?.let {
+ viewModel.getCollections(
+ it.id, true
+ )
+ }
+ },
+ navController = navController,
+ addNewButton = PlatformFeatures.addCollection,
+ instanceDomain = viewModel.ownDomain,
+ ) { url -> viewModel.openUrl(url) }
+ }
+ }
- SwitchViewComposable(postsCount = viewModel.accountState.account?.postsCount
- ?: 0,
+ item {
+ SwitchViewComposable(
+ postsCount = viewModel.accountState.account?.postsCount ?: 0,
viewType = viewModel.view,
onViewChange = { viewModel.changeView(it) })
}
- }
- PostsWrapperComposable(
- posts = viewModel.postsState.posts,
- isLoading = viewModel.postsState.isLoading,
- isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
- error = viewModel.postsState.error,
- endReached = viewModel.postsState.endReached,
- emptyMessage = EmptyState(
- icon = Icons.Outlined.Photo, heading = "No Posts"
- ),
- view = viewModel.view,
- isFirstImageLarge = true,
- postGetsDeleted = { viewModel.postGetsDeleted(it) },
- updatePost = { viewModel.updatePost(it) },
- navController = navController
- )
- /*PostsWrapperComposable(
- accountState = viewModel.accountState,
- postsState = viewModel.postsState,
- navController = navController,
- emptyState = EmptyState(
- icon = Icons.Outlined.Photo, heading = "No Posts"
- ),
- view = viewModel.view,
- postGetsDeleted = { viewModel.postGetsDeleted(it) },
- isFirstImageLarge = true
- )*/
-
- }
+ PostsWrapperComposable(
+ posts = viewModel.postsState.posts,
+ isLoading = viewModel.postsState.isLoading,
+ isRefreshing = viewModel.accountState.refreshing || viewModel.postsState.refreshing,
+ error = viewModel.postsState.error,
+ endReached = viewModel.postsState.endReached,
+ emptyMessage = EmptyState(
+ icon = Icons.Outlined.Photo, heading = "No Posts"
+ ),
+ view = viewModel.view,
+ isFirstImageLarge = true,
+ postGetsDeleted = { viewModel.postGetsDeleted(it) },
+ updatePost = { viewModel.updatePost(it) },
+ navController = navController
+ )
+ }
- if (viewModel.postsState.posts.isEmpty() && viewModel.postsState.error.isNotBlank()) {
- FullscreenErrorComposable(message = viewModel.postsState.error)
+ if (viewModel.postsState.posts.isEmpty() && viewModel.postsState.error.isNotBlank()) {
+ FullscreenErrorComposable(message = viewModel.postsState.error)
+ }
}
}
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Row(Modifier.clickable { showBottomSheet = 2 }) {
+ Column {
+ Text(
+ text = viewModel.accountState.account?.username ?: "",
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ Text(
+ text = viewModel.ownDomain, fontSize = 12.sp, lineHeight = 6.sp
+ )
+ }
+ }
+ }, actions = {
+ if (viewModel.ownDomain.isNotEmpty()) {
+ DomainSoftwareComposable(
+ domain = viewModel.ownDomain
+ )
+ }
+
+ IconButton(onClick = {
+ showBottomSheet = 1
+ }) {
+ Icon(
+ imageVector = Icons.Outlined.MoreVert, contentDescription = "preferences"
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
InfiniteListHandler(lazyListState = lazyGridState) {
@@ -217,12 +215,15 @@ fun OwnProfileComposable(
) {
if (showBottomSheet == 1) {
val icon = viewModel.appIcon.collectAsState()
- ModalBottomSheetContent(navController = navController,
+ ModalBottomSheetContent(
+ navController = navController,
instanceDomain = viewModel.ownDomain,
appIcon = icon.value,
closeBottomSheet = {
showBottomSheet = 0
- }, openPreferencesDrawer)
+ },
+ openPreferencesDrawer
+ )
} else if (showBottomSheet == 2) {
AccountSwitchBottomSheet(
navController = navController,
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_instance/AboutInstanceComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_instance/AboutInstanceComposable.kt
index 04720463..a1bc87a8 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_instance/AboutInstanceComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_instance/AboutInstanceComposable.kt
@@ -1,29 +1,34 @@
package com.daniebeler.pfpixelix.ui.composables.settings.about_instance
+import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -40,10 +45,8 @@ import com.daniebeler.pfpixelix.ui.navigation.Destination
import com.daniebeler.pfpixelix.utils.StringFormat
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.admin
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.default_avatar
import pixelix.app.generated.resources.instance_version
import pixelix.app.generated.resources.posts
@@ -61,197 +64,215 @@ fun AboutInstanceComposable(
) {
val lazyListState = rememberLazyListState()
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(text = viewModel.ownInstanceDomain, fontWeight = FontWeight.Bold)
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- })
- }) { paddingValues ->
- LazyColumn(
- modifier = Modifier.padding(paddingValues), state = lazyListState
+
+ Box(modifier = Modifier.fillMaxSize()) {
+
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
+
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
+ .fillMaxSize()
) {
- if (!viewModel.instanceState.isLoading && viewModel.instanceState.error.isEmpty()) {
- item {
- AsyncImage(
- model = viewModel.instanceState.instance?.thumbnailUrl,
- contentDescription = null,
- modifier = Modifier.fillMaxWidth()
- )
- Spacer(modifier = Modifier.height(18.dp))
- Text(
- text = viewModel.instanceState.instance?.description ?: "",
- Modifier.padding(12.dp, 0.dp)
- )
- Spacer(modifier = Modifier.height(18.dp))
+ LazyColumn(
+ state = lazyListState
+ ) {
+ if (!viewModel.instanceState.isLoading && viewModel.instanceState.error.isEmpty()) {
+ item {
+ Box(
+ Modifier.fillParentMaxWidth().height(24.dp)
+ .background(MaterialTheme.colorScheme.surfaceContainer)
+ )
+ AsyncImage(
+ model = viewModel.instanceState.instance?.thumbnailUrl,
+ contentDescription = null,
+ modifier = Modifier.fillMaxWidth()
+ )
+ Spacer(modifier = Modifier.height(18.dp))
+ Text(
+ text = viewModel.instanceState.instance?.description ?: "",
+ Modifier.padding(12.dp, 0.dp)
+ )
+ Spacer(modifier = Modifier.height(18.dp))
- Text(
- text = stringResource(Res.string.stats),
- fontWeight = FontWeight.Bold,
- fontSize = 18.sp,
- modifier = Modifier.padding(12.dp, 0.dp)
- )
+ Text(
+ text = stringResource(Res.string.stats),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ modifier = Modifier.padding(12.dp, 0.dp)
+ )
- Row(
- horizontalArrangement = Arrangement.SpaceEvenly,
- modifier = Modifier.fillMaxWidth()
- ) {
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
- Text(
- text = StringFormat.groupDigits(
- viewModel.instanceState.instance?.stats?.userCount
- ), fontWeight = FontWeight.Bold, fontSize = 18.sp
- )
- Text(text = stringResource(Res.string.users), fontSize = 12.sp)
+ Row(
+ horizontalArrangement = Arrangement.SpaceEvenly,
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ Text(
+ text = StringFormat.groupDigits(
+ viewModel.instanceState.instance?.stats?.userCount
+ ), fontWeight = FontWeight.Bold, fontSize = 18.sp
+ )
+ Text(text = stringResource(Res.string.users), fontSize = 12.sp)
+ }
+
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ Text(
+ text = StringFormat.groupDigits(
+ viewModel.instanceState.instance?.stats?.statusCount
+ ), fontWeight = FontWeight.Bold, fontSize = 18.sp
+ )
+ Text(text = stringResource(Res.string.posts), fontSize = 12.sp)
+ }
}
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ Spacer(modifier = Modifier.height(18.dp))
+
+ viewModel.instanceState.instance?.admin?.let { account ->
Text(
- text = StringFormat.groupDigits(
- viewModel.instanceState.instance?.stats?.statusCount
- ), fontWeight = FontWeight.Bold, fontSize = 18.sp
+ text = stringResource(Res.string.admin),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ modifier = Modifier.padding(12.dp, 0.dp)
)
- Text(text = stringResource(Res.string.posts), fontSize = 12.sp)
+
+ Row(
+ modifier = Modifier.clickable {
+ navController.navigate(Destination.Profile(account.id))
+ }.padding(horizontal = 12.dp, vertical = 8.dp).fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ AsyncImage(
+ model = account.avatar,
+ error = painterResource(Res.drawable.default_avatar),
+ contentDescription = "",
+ modifier = Modifier.height(46.dp).width(46.dp).clip(CircleShape)
+ )
+ Spacer(modifier = Modifier.width(10.dp))
+ Column {
+ if (account.displayname != null) {
+ Text(text = account.displayname)
+ }
+ Text(text = "@${account.username}")
+ }
+ }
}
- }
- Spacer(modifier = Modifier.height(18.dp))
+ Spacer(modifier = Modifier.height(18.dp))
- viewModel.instanceState.instance?.admin?.let { account ->
Text(
- text = stringResource(Res.string.admin),
+ text = stringResource(Res.string.privacy_policy),
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
modifier = Modifier.padding(12.dp, 0.dp)
)
- Row(modifier = Modifier
- .clickable {
- navController.navigate(Destination.Profile(account.id))
- }
- .padding(horizontal = 12.dp, vertical = 8.dp)
- .fillMaxWidth(),
- verticalAlignment = Alignment.CenterVertically) {
- AsyncImage(
- model = account.avatar,
- error = painterResource(Res.drawable.default_avatar),
- contentDescription = "",
- modifier = Modifier
- .height(46.dp)
- .width(46.dp)
- .clip(CircleShape)
- )
- Spacer(modifier = Modifier.width(10.dp))
- Column {
- if (account.displayname != null) {
- Text(text = account.displayname)
+ Text(
+ text = "https://" + viewModel.instanceState.instance?.domain + "/site/privacy",
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.padding(12.dp, 0.dp).clickable {
+ if (viewModel.instanceState.instance != null) {
+ viewModel.openUrl(
+ url = "https://" + viewModel.instanceState.instance!!.domain + "/site/privacy"
+ )
}
- Text(text = "@${account.username}")
- }
- }
- }
+ })
- Spacer(modifier = Modifier.height(18.dp))
- Text(
- text = stringResource(Res.string.privacy_policy),
- fontWeight = FontWeight.Bold,
- fontSize = 18.sp,
- modifier = Modifier.padding(12.dp, 0.dp)
- )
+ Spacer(modifier = Modifier.height(18.dp))
- Text(text = "https://" + viewModel.instanceState.instance?.domain + "/site/privacy",
- color = MaterialTheme.colorScheme.primary,
- modifier = Modifier
- .padding(12.dp, 0.dp)
- .clickable {
- if (viewModel.instanceState.instance != null) {
- viewModel.openUrl(
- url = "https://" + viewModel.instanceState.instance!!.domain + "/site/privacy"
- )
- }
- })
+ Text(
+ text = stringResource(Res.string.terms_of_use),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ modifier = Modifier.padding(12.dp, 0.dp)
+ )
- Spacer(modifier = Modifier.height(18.dp))
+ Text(
+ text = "https://" + viewModel.instanceState.instance?.domain + "/site/terms",
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.padding(12.dp, 0.dp).clickable {
+ if (viewModel.instanceState.instance != null) {
+ viewModel.openUrl(
+ url = "https://" + viewModel.instanceState.instance!!.domain + "/site/terms"
+ )
+ }
+ })
- Text(
- text = stringResource(Res.string.terms_of_use),
- fontWeight = FontWeight.Bold,
- fontSize = 18.sp,
- modifier = Modifier.padding(12.dp, 0.dp)
- )
+ Spacer(modifier = Modifier.height(18.dp))
- Text(text = "https://" + viewModel.instanceState.instance?.domain + "/site/terms",
- color = MaterialTheme.colorScheme.primary,
- modifier = Modifier
- .padding(12.dp, 0.dp)
- .clickable {
- if (viewModel.instanceState.instance != null) {
- viewModel.openUrl(
- url = "https://" + viewModel.instanceState.instance!!.domain + "/site/terms"
- )
- }
- })
+ Text(
+ text = stringResource(Res.string.rules),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ modifier = Modifier.padding(12.dp, 0.dp)
+ )
+ }
+ items(viewModel.instanceState.instance?.rules ?: emptyList()) {
+ Row(modifier = Modifier.padding(vertical = 12.dp, horizontal = 12.dp)) {
+ Text(
+ text = it.id,
+ fontSize = 24.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.primary
+ )
+ Spacer(modifier = Modifier.width(18.dp))
+ Text(text = it.text)
+ }
+ }
- Spacer(modifier = Modifier.height(18.dp))
+ item {
+ Spacer(modifier = Modifier.height(18.dp))
- Text(
- text = stringResource(Res.string.rules),
- fontWeight = FontWeight.Bold,
- fontSize = 18.sp,
- modifier = Modifier.padding(12.dp, 0.dp)
- )
- }
+ Text(
+ text = stringResource(Res.string.instance_version),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ modifier = Modifier.padding(12.dp, 0.dp)
+ )
- items(viewModel.instanceState.instance?.rules ?: emptyList()) {
- Row(modifier = Modifier.padding(vertical = 12.dp, horizontal = 12.dp)) {
- Text(
- text = it.id,
- fontSize = 24.sp,
- fontWeight = FontWeight.Bold,
- color = MaterialTheme.colorScheme.primary
- )
- Spacer(modifier = Modifier.width(18.dp))
- Text(text = it.text)
+ Text(
+ text = viewModel.instanceState.instance?.version ?: "",
+ modifier = Modifier.padding(12.dp, 0.dp)
+ )
+
+ Spacer(modifier = Modifier.height(32.dp))
+ }
}
+
}
- item {
- Spacer(modifier = Modifier.height(18.dp))
+ }
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
Text(
- text = stringResource(Res.string.instance_version),
+ text = viewModel.ownInstanceDomain,
fontWeight = FontWeight.Bold,
- fontSize = 18.sp,
- modifier = Modifier.padding(12.dp, 0.dp)
- )
-
- Text(
- text = viewModel.instanceState.instance?.version ?: "",
- modifier = Modifier.padding(12.dp, 0.dp)
+ fontSize = 18.sp
)
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
- Spacer(modifier = Modifier.height(32.dp))
- }
+ if (viewModel.instanceState.isLoading) {
+ FullscreenLoadingComposable()
}
+ if (viewModel.instanceState.error.isNotBlank()) {
+ FullscreenErrorComposable(message = viewModel.instanceState.error)
+ }
}
-
- if (viewModel.instanceState.isLoading) {
- FullscreenLoadingComposable()
- }
-
- if (viewModel.instanceState.error.isNotBlank()) {
- FullscreenErrorComposable(message = viewModel.instanceState.error)
- }
-}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_pixelix/AboutPixelixComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_pixelix/AboutPixelixComposable.kt
index 996852eb..a51eeeec 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_pixelix/AboutPixelixComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/about_pixelix/AboutPixelixComposable.kt
@@ -3,32 +3,34 @@ package com.daniebeler.pfpixelix.ui.composables.settings.about_pixelix
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.Language
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
@@ -45,11 +47,9 @@ import com.daniebeler.pfpixelix.ui.composables.ButtonRowElement
import com.daniebeler.pfpixelix.ui.navigation.Destination
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.about_pixelix
import pixelix.app.generated.resources.browsers_outline
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.code_slash_outline
import pixelix.app.generated.resources.developed_by
import pixelix.app.generated.resources.mastodon_logo
@@ -65,236 +65,213 @@ fun AboutPixelixComposable(
) {
val scrollState = rememberScrollState()
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(text = stringResource(Res.string.about_pixelix), fontWeight = FontWeight.Bold)
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline),
- contentDescription = ""
- )
- }
- })
- }) { paddingValues ->
- Column(
- modifier = Modifier
- .padding(paddingValues)
+ Box(modifier = Modifier.fillMaxSize()) {
+
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
+
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
.fillMaxSize()
- .verticalScroll(scrollState)
) {
Column(
- modifier = Modifier
- .fillMaxWidth()
- .padding(vertical = 56.dp),
- horizontalAlignment = Alignment.CenterHorizontally
+ modifier = Modifier.fillMaxSize().verticalScroll(scrollState)
) {
- val icon = viewModel.appIcon.collectAsState()
- Image(
- painterResource(icon.value),
- contentDescription = null,
- Modifier
- .width(84.dp)
- .height(84.dp)
- .clip(CircleShape)
- )
+ Column(
+ modifier = Modifier.fillMaxWidth().padding(top = 80.dp, bottom = 56.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ val icon = viewModel.appIcon.collectAsState()
+ Image(
+ painterResource(icon.value),
+ contentDescription = null,
+ Modifier.width(84.dp).height(84.dp).clip(CircleShape)
+ )
- Spacer(modifier = Modifier.height(12.dp))
+ Spacer(modifier = Modifier.height(12.dp))
- Text(
- text = "Pixelix", fontSize = 36.sp, fontWeight = FontWeight.Bold
- )
-
- Text(
- text = "Version " + viewModel.versionName,
- fontSize = 16.sp,
- color = MaterialTheme.colorScheme.secondary
- )
+ Text(
+ text = "Pixelix", fontSize = 36.sp, fontWeight = FontWeight.Bold
+ )
- }
+ Text(
+ text = "Version " + viewModel.versionName,
+ fontSize = 16.sp,
+ color = MaterialTheme.colorScheme.secondary
+ )
- HorizontalDivider(Modifier.padding(12.dp))
+ }
- ButtonRowElement(
- icon = Res.drawable.star_outline,
- text = "Rate Pixelix on Google Play Store",
- onClick = { viewModel.rateApp() })
+ HorizontalDivider(Modifier.padding(12.dp))
- HorizontalDivider(Modifier.padding(12.dp))
+ ButtonRowElement(
+ icon = Res.drawable.star_outline,
+ text = "Rate Pixelix on Google Play Store",
+ onClick = { viewModel.rateApp() })
- ButtonRowElement(
- icon = Res.drawable.browsers_outline,
- text = "Homepage",
- smallText = "https://app.pixelix.social",
- onClick = { viewModel.openUrl("https://app.pixelix.social") })
+ HorizontalDivider(Modifier.padding(12.dp))
- ButtonRowElement(
- icon = Res.drawable.shield_outline,
- text = "Privacy Policy",
- smallText = "https://app.pixelix.social/privacy",
- onClick = { viewModel.openUrl("https://app.pixelix.social/privacy") })
+ ButtonRowElement(
+ icon = Res.drawable.browsers_outline,
+ text = "Homepage",
+ smallText = "https://app.pixelix.social",
+ onClick = { viewModel.openUrl("https://app.pixelix.social") })
- ButtonRowElement(
- icon = Res.drawable.code_slash_outline,
- text = "Source Code",
- smallText = "https://github.com/daniebeler/pixelix",
- onClick = { viewModel.openUrl("https://github.com/daniebeler/pixelix") })
+ ButtonRowElement(
+ icon = Res.drawable.shield_outline,
+ text = "Privacy Policy",
+ smallText = "https://app.pixelix.social/privacy",
+ onClick = { viewModel.openUrl("https://app.pixelix.social/privacy") })
+ ButtonRowElement(
+ icon = Res.drawable.code_slash_outline,
+ text = "Source Code",
+ smallText = "https://github.com/daniebeler/pixelix",
+ onClick = { viewModel.openUrl("https://github.com/daniebeler/pixelix") })
- HorizontalDivider(Modifier.padding(12.dp))
+ HorizontalDivider(Modifier.padding(12.dp))
- Text(
- text = stringResource(Res.string.developed_by),
- fontSize = 18.sp,
- modifier = Modifier
- .padding(12.dp, 0.dp)
- .fillMaxWidth(),
- textAlign = TextAlign.Center
- )
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 12.dp, vertical = 16.dp)
- ) {
- Text(text = "Emanuel Hiebeler", fontWeight = FontWeight.Bold)
+ Text(
+ text = stringResource(Res.string.developed_by),
+ fontSize = 18.sp,
+ modifier = Modifier.padding(12.dp, 0.dp).fillMaxWidth(),
+ textAlign = TextAlign.Center
+ )
- Row {
- Image(
- painter = painterResource(Res.drawable.pixelfed_logo),
- contentDescription = null,
- Modifier
- .width(32.dp)
- .height(32.dp)
- .clickable {
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 16.dp)
+ ) {
+ Text(text = "Emanuel Hiebeler", fontWeight = FontWeight.Bold)
+
+ Row {
+ Image(
+ painter = painterResource(Res.drawable.pixelfed_logo),
+ contentDescription = null,
+ Modifier.width(32.dp).height(32.dp).clickable {
navController.navigate(Destination.ProfileByUsername("hiebeler05@pixelix.social"))
})
- Spacer(modifier = Modifier.width(16.dp))
+ Spacer(modifier = Modifier.width(16.dp))
- Image(
- painter = painterResource(Res.drawable.mastodon_logo),
- contentDescription = null,
- Modifier
- .width(32.dp)
- .height(32.dp)
- .clickable {
+ Image(
+ painter = painterResource(Res.drawable.mastodon_logo),
+ contentDescription = null,
+ Modifier.width(32.dp).height(32.dp).clickable {
viewModel.openUrl("https://techhub.social/@Hiebeler05")
})
- Spacer(modifier = Modifier.width(16.dp))
+ Spacer(modifier = Modifier.width(16.dp))
- Icon(
- imageVector = Icons.Outlined.Language,
- contentDescription = "",
- Modifier
- .size(32.dp)
- .clickable {
+ Icon(
+ imageVector = Icons.Outlined.Language,
+ contentDescription = "",
+ Modifier.size(32.dp).clickable {
viewModel.openUrl("https://emanuelhiebeler.me")
},
- tint = Color(0xFF4793FF)
- )
+ tint = Color(0xFF4793FF)
+ )
+ }
}
- }
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 12.dp, vertical = 16.dp)
- ) {
- Text(text = "Daniel Hiebeler", fontWeight = FontWeight.Bold)
-
- Row {
- Image(
- painter = painterResource(Res.drawable.pixelfed_logo),
- contentDescription = null,
- Modifier
- .width(32.dp)
- .height(32.dp)
- .clickable {
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 16.dp)
+ ) {
+ Text(text = "Daniel Hiebeler", fontWeight = FontWeight.Bold)
+
+ Row {
+ Image(
+ painter = painterResource(Res.drawable.pixelfed_logo),
+ contentDescription = null,
+ Modifier.width(32.dp).height(32.dp).clickable {
navController.navigate(Destination.ProfileByUsername("daniebeler@pixelix.social"))
})
- Spacer(modifier = Modifier.width(16.dp))
+ Spacer(modifier = Modifier.width(16.dp))
- Image(
- painter = painterResource(Res.drawable.mastodon_logo),
- contentDescription = null,
- Modifier
- .width(32.dp)
- .height(32.dp)
- .clickable {
+ Image(
+ painter = painterResource(Res.drawable.mastodon_logo),
+ contentDescription = null,
+ Modifier.width(32.dp).height(32.dp).clickable {
viewModel.openUrl("https://techhub.social/@daniebeler")
})
- Spacer(modifier = Modifier.width(16.dp))
+ Spacer(modifier = Modifier.width(16.dp))
- Icon(
- imageVector = Icons.Outlined.Language,
- contentDescription = "",
- Modifier
- .size(32.dp)
- .clickable {
+ Icon(
+ imageVector = Icons.Outlined.Language,
+ contentDescription = "",
+ Modifier.size(32.dp).clickable {
viewModel.openUrl("https://daniebeler.com")
},
- tint = Color(0xFF4793FF)
- )
+ tint = Color(0xFF4793FF)
+ )
+ }
}
- }
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 12.dp, vertical = 16.dp)
- ) {
- Text(text = "Konstantin Tskhovrebov", fontWeight = FontWeight.Bold)
-
- Row {
- Image(
- painter = painterResource(Res.drawable.pixelfed_logo),
- contentDescription = null,
- Modifier
- .width(32.dp)
- .height(32.dp)
- .clickable {
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 16.dp)
+ ) {
+ Text(text = "Konstantin Tskhovrebov", fontWeight = FontWeight.Bold)
+
+ Row {
+ Image(
+ painter = painterResource(Res.drawable.pixelfed_logo),
+ contentDescription = null,
+ Modifier.width(32.dp).height(32.dp).clickable {
navController.navigate(Destination.ProfileByUsername("dagboek@pixey.org"))
})
- Spacer(modifier = Modifier.width(16.dp))
+ Spacer(modifier = Modifier.width(16.dp))
- Image(
- painter = painterResource(Res.drawable.mastodon_logo),
- contentDescription = null,
- Modifier
- .width(32.dp)
- .height(32.dp)
- .clickable {
+ Image(
+ painter = painterResource(Res.drawable.mastodon_logo),
+ contentDescription = null,
+ Modifier.width(32.dp).height(32.dp).clickable {
viewModel.openUrl("https://androiddev.social/@terrakok")
})
- Spacer(modifier = Modifier.width(16.dp))
+ Spacer(modifier = Modifier.width(16.dp))
- Icon(
- imageVector = Icons.Outlined.Language,
- contentDescription = "",
- Modifier
- .size(32.dp)
- .clickable {
+ Icon(
+ imageVector = Icons.Outlined.Language,
+ contentDescription = "",
+ Modifier.size(32.dp).clickable {
viewModel.openUrl("https://github.com/terrakok")
},
- tint = Color(0xFF4793FF)
- )
+ tint = Color(0xFF4793FF)
+ )
+ }
}
}
}
+
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ text = stringResource(Res.string.about_pixelix),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
}
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/blocked_accounts/BlockedAccountsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/blocked_accounts/BlockedAccountsComposable.kt
index 4608e1ee..fe2df812 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/blocked_accounts/BlockedAccountsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/blocked_accounts/BlockedAccountsComposable.kt
@@ -1,26 +1,32 @@
package com.daniebeler.pfpixelix.ui.composables.settings.blocked_accounts
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
-import androidx.compose.material3.Scaffold
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
@@ -28,43 +34,30 @@ import com.daniebeler.pfpixelix.ui.composables.states.FullscreenEmptyStateCompos
import com.daniebeler.pfpixelix.ui.composables.states.FullscreenErrorComposable
import com.daniebeler.pfpixelix.ui.composables.states.FullscreenLoadingComposable
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.blocked_accounts
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.no_blocked_accounts
-@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BlockedAccountsComposable(
navController: NavController,
viewModel: BlockedAccountsViewModel = injectViewModel(key = "blocked-accounts-key") { blockedAccountsViewModel }
) {
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(
- text = stringResource(Res.string.blocked_accounts), fontWeight = FontWeight.Bold
- )
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- })
+ Box(modifier = Modifier.fillMaxSize()) {
+
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- }) { paddingValues ->
Box(
- modifier = Modifier.padding(paddingValues)
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
+ .fillMaxSize()
) {
PullToRefreshBox(
isRefreshing = viewModel.blockedAccountsState.isRefreshing,
onRefresh = { viewModel.getBlockedAccounts(true) },
) {
LazyColumn(
- modifier = Modifier.fillMaxSize()
+ modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues(top = 24.dp)
) {
items(viewModel.blockedAccountsState.blockedAccounts, key = {
it.id
@@ -78,18 +71,41 @@ fun BlockedAccountsComposable(
}
}
- if (viewModel.blockedAccountsState.blockedAccounts.isEmpty()) {
- if (viewModel.blockedAccountsState.isLoading && !viewModel.blockedAccountsState.isRefreshing) {
- FullscreenLoadingComposable()
- }
+ }
- if (viewModel.blockedAccountsState.error.isNotEmpty()) {
- FullscreenErrorComposable(message = viewModel.blockedAccountsState.error)
- }
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ text = stringResource(Res.string.blocked_accounts),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
- if (!viewModel.blockedAccountsState.isLoading && viewModel.blockedAccountsState.error.isEmpty()) {
- FullscreenEmptyStateComposable(EmptyState(heading = stringResource(Res.string.no_blocked_accounts)))
- }
+ if (viewModel.blockedAccountsState.blockedAccounts.isEmpty()) {
+ if (viewModel.blockedAccountsState.isLoading && !viewModel.blockedAccountsState.isRefreshing) {
+ FullscreenLoadingComposable()
+ }
+
+ if (viewModel.blockedAccountsState.error.isNotEmpty()) {
+ FullscreenErrorComposable(message = viewModel.blockedAccountsState.error)
+ }
+
+ if (!viewModel.blockedAccountsState.isLoading && viewModel.blockedAccountsState.error.isEmpty()) {
+ FullscreenEmptyStateComposable(EmptyState(heading = stringResource(Res.string.no_blocked_accounts)))
}
}
}
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/bookmarked_posts/BookmarkedPostsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/bookmarked_posts/BookmarkedPostsComposable.kt
index 6d8f3d87..03c8a1df 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/bookmarked_posts/BookmarkedPostsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/bookmarked_posts/BookmarkedPostsComposable.kt
@@ -2,29 +2,33 @@ package com.daniebeler.pfpixelix.ui.composables.settings.bookmarked_posts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.foundation.layout.statusBars
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
-import androidx.compose.material3.Scaffold
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.InfinitePostsGrid
import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.bookmarked_posts
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.no_bookmarked_posts
@OptIn(ExperimentalMaterial3Api::class)
@@ -34,26 +38,16 @@ fun BookmarkedPostsComposable(
viewModel: BookmarkedPostsViewModel = injectViewModel(key = "bookmarksviewmodel") { bookmarkedPostsViewModel }
) {
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(stringResource(Res.string.bookmarked_posts), fontWeight = FontWeight.Bold)
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- })
+ Box(modifier = Modifier.fillMaxSize()) {
+
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- }) { paddingValues ->
Box(
- modifier = Modifier
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
.fillMaxSize()
- .padding(paddingValues)
) {
- InfinitePostsGrid(items = viewModel.bookmarkedPostsState.bookmarkedPosts,
+ InfinitePostsGrid(
+ items = viewModel.bookmarkedPostsState.bookmarkedPosts,
isLoading = viewModel.bookmarkedPostsState.isLoading,
isRefreshing = viewModel.bookmarkedPostsState.isRefreshing,
error = viewModel.bookmarkedPostsState.error,
@@ -61,7 +55,31 @@ fun BookmarkedPostsComposable(
emptyMessage = EmptyState(heading = stringResource(Res.string.no_bookmarked_posts)),
navController = navController,
getItemsPaginated = { /*TODO*/ },
- onRefresh = { viewModel.getBookmarkedPosts(true) })
+ onRefresh = { viewModel.getBookmarkedPosts(true) },
+ contentPaddingTop = 24.dp
+ )
}
+
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ stringResource(Res.string.bookmarked_posts),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/followed_hashtags/FollowedHashtagsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/followed_hashtags/FollowedHashtagsComposable.kt
index bf069fa8..1384f475 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/followed_hashtags/FollowedHashtagsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/followed_hashtags/FollowedHashtagsComposable.kt
@@ -1,28 +1,34 @@
package com.daniebeler.pfpixelix.ui.composables.settings.followed_hashtags
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.Tag
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
-import androidx.compose.material3.Scaffold
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.CustomHashtag
@@ -32,9 +38,7 @@ import com.daniebeler.pfpixelix.ui.composables.states.FullscreenErrorComposable
import com.daniebeler.pfpixelix.ui.composables.states.FullscreenLoadingComposable
import com.daniebeler.pfpixelix.ui.navigation.Destination
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.followed_hashtags
import pixelix.app.generated.resources.no_followed_hashtags
@@ -44,57 +48,76 @@ fun FollowedHashtagsComposable(
navController: NavController,
viewModel: FollowedHashtagsViewModel = injectViewModel(key = "followed-hashtags-key") { followedHashtagsViewModel }
) {
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(stringResource(Res.string.followed_hashtags), fontWeight = FontWeight.Bold)
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- })
+ Box(modifier = Modifier.fillMaxSize()) {
- }) { paddingValues ->
- PullToRefreshBox(
- isRefreshing = viewModel.followedHashtagsState.isRefreshing,
- onRefresh = { viewModel.getFollowedHashtags(true) },
- modifier = Modifier
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
+
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
.fillMaxSize()
- .padding(paddingValues)
) {
- LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp),
- modifier = Modifier.fillMaxSize(),
- content = {
- items(viewModel.followedHashtagsState.followedHashtags) { tag ->
- CustomHashtag(hashtag = tag, navController = navController)
+ PullToRefreshBox(
+ isRefreshing = viewModel.followedHashtagsState.isRefreshing,
+ onRefresh = { viewModel.getFollowedHashtags(true) },
+ modifier = Modifier.fillMaxSize()
+ ) {
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(4.dp),
+ contentPadding = PaddingValues(top = 24.dp),
+ modifier = Modifier.fillMaxSize(),
+ content = {
+ items(viewModel.followedHashtagsState.followedHashtags) { tag ->
+ CustomHashtag(hashtag = tag, navController = navController)
+ }
+ })
+
+ if (viewModel.followedHashtagsState.followedHashtags.isEmpty()) {
+ if (viewModel.followedHashtagsState.isLoading && !viewModel.followedHashtagsState.isRefreshing) {
+ FullscreenLoadingComposable()
}
- })
- if (viewModel.followedHashtagsState.followedHashtags.isEmpty()) {
- if (viewModel.followedHashtagsState.isLoading && !viewModel.followedHashtagsState.isRefreshing) {
- FullscreenLoadingComposable()
- }
+ if (viewModel.followedHashtagsState.error.isNotEmpty()) {
+ FullscreenErrorComposable(message = viewModel.followedHashtagsState.error)
+ }
- if (viewModel.followedHashtagsState.error.isNotEmpty()) {
- FullscreenErrorComposable(message = viewModel.followedHashtagsState.error)
+ if (!viewModel.followedHashtagsState.isLoading && viewModel.followedHashtagsState.error.isEmpty()) {
+ FullscreenEmptyStateComposable(
+ EmptyState(
+ icon = Icons.Outlined.Tag,
+ heading = stringResource(Res.string.no_followed_hashtags),
+ message = "Followed hashtags will appear here",
+ buttonText = "Explore trending hashtags",
+ onClick = {
+ navController.navigate(Destination.Search(2))
+ })
+ )
+ }
}
+ }
+
+ }
- if (!viewModel.followedHashtagsState.isLoading && viewModel.followedHashtagsState.error.isEmpty()) {
- FullscreenEmptyStateComposable(
- EmptyState(icon = Icons.Outlined.Tag,
- heading = stringResource(Res.string.no_followed_hashtags),
- message = "Followed hashtags will appear here",
- buttonText = "Explore trending hashtags",
- onClick = {
- navController.navigate(Destination.Search(2))
- })
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ stringResource(Res.string.followed_hashtags),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
)
}
- }
- }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/icon_selection/IconSelectionComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/icon_selection/IconSelectionComposable.kt
index e9e3ea4b..2d8652c5 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/icon_selection/IconSelectionComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/icon_selection/IconSelectionComposable.kt
@@ -6,8 +6,7 @@ import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.aspectRatio
@@ -17,21 +16,23 @@ import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.grid.GridCells
-import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
@@ -41,20 +42,17 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.cancel
import pixelix.app.generated.resources.change
import pixelix.app.generated.resources.change_app_icon
import pixelix.app.generated.resources.change_app_icon_dialog_content
-import pixelix.app.generated.resources.chevron_back_outline
-import pixelix.app.generated.resources.two_icons_info
-
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -65,24 +63,10 @@ fun IconSelectionComposable(
val lazyGridState = rememberLazyGridState()
val (newIcon, setNewIcon) = remember { mutableStateOf(null) }
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text("Icon Selection", fontWeight = FontWeight.Bold)
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline),
- contentDescription = ""
- )
- }
- })
-
- }) { paddingValues ->
+ Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top)) { paddingValues ->
Box(
- modifier = Modifier
- .fillMaxSize()
+ modifier = Modifier.fillMaxSize()
+ .padding(top = TopAppBarDefaults.TopAppBarExpandedHeight - 24.dp)
.padding(paddingValues)
) {
@@ -90,9 +74,8 @@ fun IconSelectionComposable(
LazyVerticalGrid(
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 12.dp),
+ contentPadding = PaddingValues(top = 30.dp),
+ modifier = Modifier.fillMaxSize().padding(horizontal = 12.dp),
state = lazyGridState,
columns = GridCells.Fixed(3)
) {
@@ -101,21 +84,15 @@ fun IconSelectionComposable(
painterResource(icon),
contentDescription = null,
contentScale = ContentScale.Crop,
- modifier = Modifier
- .padding(6.dp)
- .fillMaxWidth()
- .aspectRatio(1f)
- .clip(CircleShape)
- .let {
+ modifier = Modifier.padding(6.dp).fillMaxWidth().aspectRatio(1f)
+ .clip(CircleShape).let {
if (selectedIcon.value == icon) {
it.border(
BorderStroke(4.dp, MaterialTheme.colorScheme.primary),
shape = CircleShape
)
} else it
- }
- .clickable { setNewIcon(icon) }
- )
+ }.clickable { setNewIcon(icon) })
}
}
@@ -123,6 +100,24 @@ fun IconSelectionComposable(
}
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text("Icon Selection", fontWeight = FontWeight.Bold, fontSize = 18.sp)
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
+
if (newIcon != null) {
AlertDialog(title = {
Text(text = stringResource(Res.string.change_app_icon))
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/liked_posts/LikedPostsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/liked_posts/LikedPostsComposable.kt
index 18507f96..a116c787 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/liked_posts/LikedPostsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/liked_posts/LikedPostsComposable.kt
@@ -2,30 +2,33 @@ package com.daniebeler.pfpixelix.ui.composables.settings.liked_posts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.FavoriteBorder
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
-import androidx.compose.material3.Scaffold
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.InfinitePostsGrid
import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.liked_posts
import pixelix.app.generated.resources.no_liked_posts
@@ -36,27 +39,13 @@ fun LikedPostsComposable(
viewModel: LikedPostsViewModel = injectViewModel(key = "likey-posts-key") { likedPostsViewModel }
) {
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(stringResource(Res.string.liked_posts), fontWeight = FontWeight.Bold)
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- })
+ Box(modifier = Modifier.fillMaxSize()) {
- }) { paddingValues ->
- Box(
- modifier = Modifier
- .fillMaxSize()
- .padding(paddingValues)
- ) {
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- InfinitePostsGrid(items = viewModel.likedPostsState.likedPosts,
+ Box(modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp).fillMaxSize()) {
+ InfinitePostsGrid(
+ items = viewModel.likedPostsState.likedPosts,
isLoading = viewModel.likedPostsState.isLoading,
isRefreshing = viewModel.likedPostsState.isRefreshing,
error = viewModel.likedPostsState.error,
@@ -65,13 +54,29 @@ fun LikedPostsComposable(
heading = stringResource(Res.string.no_liked_posts)
),
navController = navController,
- getItemsPaginated = {
- viewModel.getItemsPaginated()
- },
- onRefresh = {
- viewModel.getItemsFirstLoad(true)
- })
+ getItemsPaginated = { viewModel.getItemsPaginated() },
+ onRefresh = { viewModel.getItemsFirstLoad(true) },
+ contentPaddingTop = 24.dp)
}
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ stringResource(Res.string.liked_posts),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, navigationIcon = {
+ IconButton(onClick = { navController.popBackStack() }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/muted_accounts/MutedAccountsComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/muted_accounts/MutedAccountsComposable.kt
index 5189c6a6..39b24f6d 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/muted_accounts/MutedAccountsComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/muted_accounts/MutedAccountsComposable.kt
@@ -1,25 +1,33 @@
package com.daniebeler.pfpixelix.ui.composables.settings.muted_accounts
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
-import androidx.compose.material3.Scaffold
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
@@ -27,9 +35,7 @@ import com.daniebeler.pfpixelix.ui.composables.states.FullscreenEmptyStateCompos
import com.daniebeler.pfpixelix.ui.composables.states.FullscreenErrorComposable
import com.daniebeler.pfpixelix.ui.composables.states.FullscreenLoadingComposable
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.muted_accounts
import pixelix.app.generated.resources.no_muted_accounts
@@ -39,56 +45,71 @@ fun MutedAccountsComposable(
navController: NavController,
viewModel: MutedAccountsViewModel = injectViewModel(key = "muted-accounts-key") { mutedAccountsViewModel }
) {
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Text(text = stringResource(Res.string.muted_accounts), fontWeight = FontWeight.Bold)
- }, navigationIcon = {
- IconButton(onClick = {
- navController.popBackStack()
- }) {
- Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
- )
- }
- })
+ Box(modifier = Modifier.fillMaxSize()) {
+
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- }) { paddingValues ->
- PullToRefreshBox(
- onRefresh = {viewModel.getMutedAccounts(true)},
- isRefreshing = viewModel.mutedAccountsState.isRefreshing,
- modifier = Modifier
+ Box(
+ modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp)
.fillMaxSize()
- .padding(paddingValues)
) {
- LazyColumn(
- modifier = Modifier
- .fillMaxSize()
+ PullToRefreshBox(
+ onRefresh = { viewModel.getMutedAccounts(true) },
+ isRefreshing = viewModel.mutedAccountsState.isRefreshing,
+ modifier = Modifier.fillMaxSize()
) {
- items(viewModel.mutedAccountsState.mutedAccounts, key = {
- it.id
- }) {
- Row {
- CustomMutedAccountRow(
- account = it, navController = navController, viewModel
- )
+ LazyColumn(
+ contentPadding = PaddingValues(top = 24.dp), modifier = Modifier.fillMaxSize()
+ ) {
+ items(viewModel.mutedAccountsState.mutedAccounts, key = {
+ it.id
+ }) {
+ Row {
+ CustomMutedAccountRow(
+ account = it, navController = navController, viewModel
+ )
+ }
}
}
- }
- if (viewModel.mutedAccountsState.mutedAccounts.isEmpty()) {
- if (viewModel.mutedAccountsState.isLoading && !viewModel.mutedAccountsState.isRefreshing) {
- FullscreenLoadingComposable()
- }
+ if (viewModel.mutedAccountsState.mutedAccounts.isEmpty()) {
+ if (viewModel.mutedAccountsState.isLoading && !viewModel.mutedAccountsState.isRefreshing) {
+ FullscreenLoadingComposable()
+ }
- if (viewModel.mutedAccountsState.error.isNotEmpty()) {
- FullscreenErrorComposable(message = viewModel.mutedAccountsState.error)
- }
+ if (viewModel.mutedAccountsState.error.isNotEmpty()) {
+ FullscreenErrorComposable(message = viewModel.mutedAccountsState.error)
+ }
- if (!viewModel.mutedAccountsState.isLoading && viewModel.mutedAccountsState.error.isEmpty()) {
- FullscreenEmptyStateComposable(EmptyState(heading = stringResource(Res.string.no_muted_accounts)))
+ if (!viewModel.mutedAccountsState.isLoading && viewModel.mutedAccountsState.error.isEmpty()) {
+ FullscreenEmptyStateComposable(EmptyState(heading = stringResource(Res.string.no_muted_accounts)))
+ }
}
}
+
}
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Text(
+ text = stringResource(Res.string.muted_accounts),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
+ )
+ }, navigationIcon = {
+ IconButton(onClick = {
+ navController.popBackStack()
+ }) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ )
+ }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
+
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/preferences/prefs/PreferencesComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/preferences/prefs/PreferencesComposable.kt
index ab1083e2..bd7caafd 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/preferences/prefs/PreferencesComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/settings/preferences/prefs/PreferencesComposable.kt
@@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.DrawerState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
@@ -19,12 +18,12 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
-import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -64,8 +63,8 @@ fun PreferencesComposable(
contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top),
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
- CenterAlignedTopAppBar(scrollBehavior = scrollBehavior, title = {
- Text(text = stringResource(Res.string.settings), fontWeight = FontWeight.Bold)
+ TopAppBar(scrollBehavior = scrollBehavior, title = {
+ Text(text = stringResource(Res.string.settings), fontWeight = FontWeight.Bold, fontSize = 18.sp)
}, navigationIcon = {
IconButton(onClick = {
closePreferencesDrawer()
@@ -78,12 +77,8 @@ fun PreferencesComposable(
})
}) { paddingValues ->
Column(
- Modifier
- .padding(paddingValues)
- .padding(horizontal = 18.dp)
- .padding(bottom = 18.dp)
- .fillMaxSize()
- .verticalScroll(state = rememberScrollState()),
+ Modifier.padding(paddingValues).padding(horizontal = 18.dp).padding(bottom = 18.dp)
+ .fillMaxSize().verticalScroll(state = rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/single_post/SinglePostComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/single_post/SinglePostComposable.kt
index 9701580c..1be5b86f 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/single_post/SinglePostComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/single_post/SinglePostComposable.kt
@@ -9,18 +9,24 @@ import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
@@ -29,10 +35,8 @@ import com.daniebeler.pfpixelix.ui.composables.states.ErrorComposable
import com.daniebeler.pfpixelix.ui.composables.states.LoadingComposable
import com.daniebeler.pfpixelix.ui.navigation.Destination
import org.jetbrains.compose.resources.stringResource
-import org.jetbrains.compose.resources.vectorResource
import pixelix.app.generated.resources.Res
import pixelix.app.generated.resources.by
-import pixelix.app.generated.resources.chevron_back_outline
import pixelix.app.generated.resources.post
@OptIn(ExperimentalMaterial3Api::class)
@@ -57,11 +61,36 @@ fun SinglePostComposable(
}
}
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top), topBar = {
- CenterAlignedTopAppBar(title = {
- Column (horizontalAlignment = Alignment.CenterHorizontally) {
+ Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top)) { paddingValues ->
+ Box(
+ modifier = Modifier.padding(paddingValues).padding(top = TopAppBarDefaults.TopAppBarExpandedHeight - 24.dp)
+ .fillMaxSize()
+ ) {
+ Column(modifier = Modifier.verticalScroll(scrollState).padding(top = 28.dp, start = 4.dp, end = 4.dp, bottom = 28.dp)) {
+ if (viewModel.postState.post != null) {
+ PostComposable(
+ viewModel.postState.post!!, navController, postGetsDeleted = {
+ navController.navigate(Destination.OwnProfile) {
+ popUpTo(0) { inclusive = true }
+ }
+ }, setZindex = { }, openReplies
+ )
+ }
+ }
+
+ LoadingComposable(isLoading = viewModel.postState.isLoading)
+ ErrorComposable(message = viewModel.postState.error)
+ }
+
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ), title = {
+ Column {
Text(
- text = stringResource(Res.string.post), fontWeight = FontWeight.Bold
+ text = stringResource(Res.string.post),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp
)
Text(
text = stringResource(
@@ -74,29 +103,12 @@ fun SinglePostComposable(
navController.popBackStack()
}) {
Icon(
- imageVector = vectorResource(Res.drawable.chevron_back_outline), contentDescription = ""
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
)
}
- })
- }) { paddingValues ->
- Box(
- modifier = Modifier
- .padding(paddingValues)
- .fillMaxSize()
- ) {
- Column(modifier = Modifier.verticalScroll(scrollState)) {
- if (viewModel.postState.post != null) {
- PostComposable(viewModel.postState.post!!, navController, postGetsDeleted = {
- navController.navigate(Destination.OwnProfile) {
- popUpTo(0) { inclusive = true }
- }
- },
- setZindex = { }, openReplies)
- }
- }
-
- LoadingComposable(isLoading = viewModel.postState.isLoading)
- ErrorComposable(message = viewModel.postState.error)
- }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
+ )
+ )
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/global_timeline/GlobalTimelineComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/global_timeline/GlobalTimelineComposable.kt
index e352b8a8..9e3c6841 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/global_timeline/GlobalTimelineComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/global_timeline/GlobalTimelineComposable.kt
@@ -1,11 +1,10 @@
package com.daniebeler.pfpixelix.ui.composables.timelines.global_timeline
import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.InfinitePostsList
-import com.daniebeler.pfpixelix.ui.composables.profile.ViewEnum
-import com.daniebeler.pfpixelix.ui.composables.states.EmptyState
@Composable
fun GlobalTimelineComposable(
@@ -13,6 +12,7 @@ fun GlobalTimelineComposable(
viewModel: GlobalTimelineViewModel = injectViewModel(key = "global-timeline-key") { globalTimelineViewModel }
) {
InfinitePostsList(items = viewModel.globalTimelineState.globalTimeline,
+ contentPaddingTop = 30.dp,
isLoading = viewModel.globalTimelineState.isLoading,
isRefreshing = viewModel.globalTimelineState.refreshing,
error = viewModel.globalTimelineState.error,
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/hashtag_timeline/HashtagTimelineComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/hashtag_timeline/HashtagTimelineComposable.kt
index 35e1a1cd..9452fa1e 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/hashtag_timeline/HashtagTimelineComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/hashtag_timeline/HashtagTimelineComposable.kt
@@ -3,27 +3,29 @@ package com.daniebeler.pfpixelix.ui.composables.timelines.hashtag_timeline
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
-import androidx.compose.foundation.layout.WindowInsetsSides
-import androidx.compose.foundation.layout.only
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.systemBars
-import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.layout.statusBars
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
-import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
-import androidx.compose.material3.Scaffold
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.FollowButton
@@ -43,18 +45,39 @@ fun HashtagTimelineComposable(
viewModel.getRelatedHashtags(hashtag)
}
- val lazyGridState = rememberLazyListState()
+ Box(modifier = Modifier.fillMaxSize()) {
- val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
+ val statusBarPadding = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
- Scaffold(contentWindowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top),
- modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
- topBar = {
- CenterAlignedTopAppBar(scrollBehavior = scrollBehavior, title = {
+ Box(modifier = Modifier.padding(top = TopAppBarDefaults.TopAppBarExpandedHeight + statusBarPadding - 24.dp).fillMaxSize()) {
+ InfinitePostsList(
+ contentPaddingTop = 24.dp,
+ items = viewModel.postsState.hashtagTimeline,
+ isLoading = viewModel.postsState.isLoading,
+ isRefreshing = viewModel.postsState.isRefreshing,
+ error = viewModel.postsState.error,
+ endReached = viewModel.postsState.endReached,
+ view = viewModel.view,
+ changeView = { viewModel.changeView(it) },
+ isFirstItemLarge = true,
+ itemGetsDeleted = { viewModel.postGetsDeleted(it) },
+ getItemsPaginated = { viewModel.getItemsPaginated(hashtag) },
+ onRefresh = { viewModel.refresh() },
+ postsCount = viewModel.hashtagState.hashtag?.count ?: 0,
+ navController = navController,
+ postGetsUpdated = { viewModel.postGetsUpdated(it) })
+ }
+
+ TopAppBar(
+ modifier = Modifier.clip(
+ RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
+ ),
+ title = {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
"#$hashtag",
fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
@@ -65,35 +88,21 @@ fun HashtagTimelineComposable(
navController.popBackStack()
}) {
Icon(
- imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = ""
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+ contentDescription = ""
)
}
}, actions = {
- FollowButton(firstLoaded = viewModel.hashtagState.hashtag != null,
+ FollowButton(
+ iconButton = true,
+ firstLoaded = viewModel.hashtagState.hashtag != null,
isLoading = viewModel.hashtagState.isLoading,
isFollowing = viewModel.hashtagState.hashtag?.following ?: false,
onFollowClick = { viewModel.followHashtag(viewModel.hashtagState.hashtag!!.name) },
onUnFollowClick = { viewModel.unfollowHashtag(viewModel.hashtagState.hashtag!!.name) })
- })
-
- }) { paddingValues ->
- Box(modifier = Modifier.padding(paddingValues)) {
- InfinitePostsList(
- items = viewModel.postsState.hashtagTimeline,
- isLoading = viewModel.postsState.isLoading,
- isRefreshing = viewModel.postsState.isRefreshing,
- error = viewModel.postsState.error,
- endReached = viewModel.postsState.endReached,
- view = viewModel.view,
- changeView = { viewModel.changeView(it) },
- isFirstItemLarge = true,
- itemGetsDeleted = { viewModel.postGetsDeleted(it) },
- getItemsPaginated = { viewModel.getItemsPaginated(hashtag) },
- onRefresh = { viewModel.refresh() },
- postsCount = viewModel.hashtagState.hashtag?.count ?: 0,
- navController = navController,
- postGetsUpdated = { viewModel.postGetsUpdated(it) }
+ }, colors = TopAppBarDefaults.mediumTopAppBarColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainer
)
- }
+ )
}
}
\ No newline at end of file
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/home_timeline/HomeTimelineComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/home_timeline/HomeTimelineComposable.kt
index 4334c006..373400d5 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/home_timeline/HomeTimelineComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/home_timeline/HomeTimelineComposable.kt
@@ -6,6 +6,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.PhotoLibrary
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.InfinitePostsList
@@ -24,6 +25,7 @@ fun HomeTimelineComposable(
) {
Box(modifier = Modifier.fillMaxSize()) {
InfinitePostsList(items = viewModel.homeTimelineState.homeTimeline,
+ contentPaddingTop = 32.dp,
isLoading = viewModel.homeTimelineState.isLoading,
isRefreshing = viewModel.homeTimelineState.refreshing,
error = viewModel.homeTimelineState.error,
diff --git a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/local_timeline/LocalTimelineComposable.kt b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/local_timeline/LocalTimelineComposable.kt
index dc67c131..68d2dfe1 100644
--- a/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/local_timeline/LocalTimelineComposable.kt
+++ b/app/src/commonMain/kotlin/com/daniebeler/pfpixelix/ui/composables/timelines/local_timeline/LocalTimelineComposable.kt
@@ -1,6 +1,7 @@
package com.daniebeler.pfpixelix.ui.composables.timelines.local_timeline
import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.daniebeler.pfpixelix.di.injectViewModel
import com.daniebeler.pfpixelix.ui.composables.InfinitePostsList
@@ -12,6 +13,7 @@ fun LocalTimelineComposable(
viewModel: LocalTimelineViewModel = injectViewModel(key = "local-timeline-key") { localTimelineViewModel }
) {
InfinitePostsList(items = viewModel.localTimelineState.localTimeline,
+ contentPaddingTop = 30.dp,
isLoading = viewModel.localTimelineState.isLoading,
isRefreshing = viewModel.localTimelineState.refreshing,
error = viewModel.localTimelineState.error,
diff --git a/appstorebadgewhite.svg b/appstorebadgewhite.svg
deleted file mode 100644
index 16c0496c..00000000
--- a/appstorebadgewhite.svg
+++ /dev/null
@@ -1,46 +0,0 @@
-
diff --git a/assets/pixelix_screenshots.png b/assets/pixelix_screenshots.png
new file mode 100644
index 00000000..9ec51cdf
Binary files /dev/null and b/assets/pixelix_screenshots.png differ
diff --git a/github-image.png b/github-image.png
deleted file mode 100644
index 28bce9d9..00000000
Binary files a/github-image.png and /dev/null differ
diff --git a/google-play-button.png b/google-play-button.png
deleted file mode 100644
index 7a06997a..00000000
Binary files a/google-play-button.png and /dev/null differ
diff --git a/metadata/de/changelogs/33.txt b/metadata/de/changelogs/33.txt
new file mode 100644
index 00000000..854f41d2
--- /dev/null
+++ b/metadata/de/changelogs/33.txt
@@ -0,0 +1 @@
+- Neues Design 🎨
\ No newline at end of file
diff --git a/metadata/en-US/changelogs/33.txt b/metadata/en-US/changelogs/33.txt
new file mode 100644
index 00000000..1830d2d9
--- /dev/null
+++ b/metadata/en-US/changelogs/33.txt
@@ -0,0 +1 @@
+- New Design 🎨
\ No newline at end of file
diff --git a/metadata/fr-FR/full_description.txt b/metadata/fr-FR/full_description.txt
index 18d07801..56b19023 100644
--- a/metadata/fr-FR/full_description.txt
+++ b/metadata/fr-FR/full_description.txt
@@ -1 +1 @@
-Pixelix provides a smooth and intuitive interface for interacting with Pixelfed, the federated image-sharing social network. Designed with user experience in mind, Pixelix makes it simple to connect to your Pixelfed instance, upload photos directly from your device, and browse through your feed with ease. Whether you're a seasoned Pixelfed user or just getting started, Pixelix offers a streamlined way to share and discover visual content.
\ No newline at end of file
+Pixelix offre une interface fluide et intuitive pour interagir avec Pixelfed, le réseau social fédéré dédié au partage d’images. Conçu pour offrir une expérience utilisateur optimale, Pixelix permet de se connecter facilement à votre instance Pixelfed, d’ajouter des photos directement depuis votre appareil, et de parcourir votre fil en toute simplicité. Que vous soyez un·e utilisateur·rice chevronné·e de Pixelfed ou que vous débutiez tout juste, Pixelix offre un moyen simple et fluide de partager et découvrir du contenu visuel.
\ No newline at end of file
diff --git a/metadata/fr-FR/short_description.txt b/metadata/fr-FR/short_description.txt
index 7b39709e..a15ce780 100644
--- a/metadata/fr-FR/short_description.txt
+++ b/metadata/fr-FR/short_description.txt
@@ -1 +1 @@
-Pixelix: a user-friendly Pixelfed client for photo uploads, browsing, & sharing.
\ No newline at end of file
+Pixelix : un client Pixelfed pour publier, naviguer & partager des photos.
\ No newline at end of file