Skip to content

Commit

Permalink
Merge branch 'main' into fix-blink-favorite-icon
Browse files Browse the repository at this point in the history
  • Loading branch information
kyanro authored Sep 9, 2024
2 parents 8c44363 + 4ede1a4 commit ae4e512
Show file tree
Hide file tree
Showing 72 changed files with 983 additions and 471 deletions.
4 changes: 2 additions & 2 deletions app-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ android {
buildConfig = true
}
defaultConfig {
versionCode = 4
versionName = "1.1.0"
versionCode = 8
versionName = "1.4.0"
}
signingConfigs {
create("dev") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ private fun KaigiNavHost(
displayFeatures: PersistentList<DisplayFeature>,
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
mainNestedNavController: NavHostController = rememberNavController(),
externalNavController: ExternalNavController = rememberExternalNavController(),
) {
SharedTransitionLayout(modifier = modifier) {
Expand All @@ -144,9 +145,10 @@ private fun KaigiNavHost(
startDestination = mainScreenRoute,
) {
mainScreen(
windowSize,
navController,
externalNavController,
windowSize = windowSize,
navController = navController,
mainNestedNavController = mainNestedNavController,
externalNavController = externalNavController,
)
sessionScreens(
onNavigationIconClick = navController::popBackStack,
Expand Down Expand Up @@ -197,12 +199,14 @@ private fun KaigiNavHost(
private fun NavGraphBuilder.mainScreen(
windowSize: WindowSizeClass,
navController: NavHostController,
mainNestedNavController: NavHostController,
@Suppress("UnusedParameter")
externalNavController: ExternalNavController,
) {
mainScreen(
windowSize = windowSize,
mainNestedGraphStateHolder = KaigiAppMainNestedGraphStateHolder(),
mainNestedNavController = mainNestedNavController,
mainNestedGraph = { mainNestedNavController, contentPadding ->
nestedSessionScreens(
modifier = Modifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import androidx.window.layout.WindowInfoTracker
import dagger.hilt.android.AndroidEntryPoint
import io.github.droidkaigi.confsched.data.di.RepositoryProvider
import io.github.droidkaigi.confsched.designsystem.theme.dotGothic16FontFamily
import io.github.droidkaigi.confsched.droidkaigiui.ProvideAndroidContextToComposeResource
import io.github.droidkaigi.confsched.droidkaigiui.compositionlocal.LocalClock
import io.github.droidkaigi.confsched.droidkaigiui.isTest
import io.github.droidkaigi.confsched.model.FontFamily.DotGothic16Regular
import io.github.droidkaigi.confsched.model.FontFamily.SystemDefault
import io.github.droidkaigi.confsched.model.Settings.DoesNotExists
Expand Down Expand Up @@ -90,9 +92,10 @@ class MainActivity : ComponentActivity() {
}
}

CompositionLocalProvider(
LocalClock provides clockProvider.clock(),
) {
CompositionLocalProvider(LocalClock provides clockProvider.clock()) {
if (isTest()) {
ProvideAndroidContextToComposeResource()
}
repositoryProvider.Provide {
KaigiApp(
windowSize = windowSize,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.droidkaigi.confsched.shared

import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
Expand Down Expand Up @@ -36,6 +38,7 @@ import io.github.droidkaigi.confsched.designsystem.theme.dotGothic16FontFamily
import io.github.droidkaigi.confsched.droidkaigiui.NavHostWithSharedAxisX
import io.github.droidkaigi.confsched.droidkaigiui.SnackbarMessageEffect
import io.github.droidkaigi.confsched.droidkaigiui.UserMessageStateHolder
import io.github.droidkaigi.confsched.droidkaigiui.compositionlocal.LocalSharedTransitionScope
import io.github.droidkaigi.confsched.droidkaigiui.compositionlocal.LocalSnackbarHostState
import io.github.droidkaigi.confsched.eventmap.eventMapScreenRoute
import io.github.droidkaigi.confsched.eventmap.eventMapScreens
Expand Down Expand Up @@ -190,79 +193,94 @@ fun KaigiApp(
}
}

@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
private fun KaigiNavHost(
windowSize: WindowSizeClass,
externalNavController: ExternalNavController,
onLicenseScreenRequest: () -> Unit,
onAccessCalendarIsDenied: () -> Unit,
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
mainNestedNavController: NavHostController = rememberNavController(),
) {
NavHostWithSharedAxisX(navController = navController, startDestination = mainScreenRoute) {
mainScreen(
windowSize = windowSize,
navController = navController,
externalNavController = externalNavController,
onLicenseScreenRequest = onLicenseScreenRequest,
)
sessionScreens(
onNavigationIconClick = navController::popBackStack,
onLinkClick = externalNavController::navigate,
onCalendarRegistrationClick = { timetableItem ->
externalNavController.navigateToCalendarRegistration(
timetableItem = timetableItem,
onAccessCalendarIsDenied = onAccessCalendarIsDenied,
SharedTransitionLayout(modifier = modifier) {
CompositionLocalProvider(
LocalSharedTransitionScope provides this,
) {
NavHostWithSharedAxisX(
navController = navController,
startDestination = mainScreenRoute,
) {
mainScreen(
windowSize = windowSize,
navController = navController,
mainNestedNavController = mainNestedNavController,
externalNavController = externalNavController,
onLicenseScreenRequest = onLicenseScreenRequest,
)
},
onShareClick = externalNavController::onShareClick,
onFavoriteListClick = {
navController.navigate(
favoritesScreenWithNavigationIconRoute
sessionScreens(
onNavigationIconClick = navController::popBackStack,
onLinkClick = externalNavController::navigate,
onCalendarRegistrationClick = { timetableItem ->
externalNavController.navigateToCalendarRegistration(
timetableItem = timetableItem,
onAccessCalendarIsDenied = onAccessCalendarIsDenied,
)
},
onShareClick = externalNavController::onShareClick,
onFavoriteListClick = {
navController.navigate(
favoritesScreenWithNavigationIconRoute
)
},
)
},
)

contributorsScreens(
onNavigationIconClick = navController::popBackStack,
onContributorItemClick = externalNavController::navigate,
)
contributorsScreens(
onNavigationIconClick = navController::popBackStack,
onContributorItemClick = externalNavController::navigate,
)

searchScreens(
onTimetableItemClick = navController::navigateToTimetableItemDetailScreen,
onBackClick = navController::popBackStack,
)
searchScreens(
onTimetableItemClick = navController::navigateToTimetableItemDetailScreen,
onBackClick = navController::popBackStack,
)

staffScreens(
onNavigationIconClick = navController::popBackStack,
onStaffItemClick = externalNavController::navigate,
)
staffScreens(
onNavigationIconClick = navController::popBackStack,
onStaffItemClick = externalNavController::navigate,
)

settingsScreens(
onNavigationIconClick = navController::popBackStack,
)
settingsScreens(
onNavigationIconClick = navController::popBackStack,
)

sponsorsScreens(
onNavigationIconClick = navController::popBackStack,
onSponsorsItemClick = externalNavController::navigate,
)
sponsorsScreens(
onNavigationIconClick = navController::popBackStack,
onSponsorsItemClick = externalNavController::navigate,
)

favoritesScreens(
onNavigationIconClick = navController::popBackStack,
onTimetableItemClick = navController::navigateToTimetableItemDetailScreen,
contentPadding = PaddingValues(),
)
favoritesScreens(
onNavigationIconClick = navController::popBackStack,
onTimetableItemClick = navController::navigateToTimetableItemDetailScreen,
contentPadding = PaddingValues(),
)
}
}
}
}

private fun NavGraphBuilder.mainScreen(
windowSize: WindowSizeClass,
navController: NavHostController,
mainNestedNavController: NavHostController,
externalNavController: ExternalNavController,
onLicenseScreenRequest: () -> Unit,
) {
mainScreen(
windowSize = windowSize,
mainNestedGraphStateHolder = KaigiAppMainNestedGraphStateHolder(),
mainNestedNavController = mainNestedNavController,
mainNestedGraph = { mainNestedNavController, contentPadding ->
nestedSessionScreens(
modifier = Modifier,
Expand Down
2 changes: 2 additions & 0 deletions app-ios/App/DroidKaigi2024App-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
</array>
<key>NSCalendarsUsageDescription</key>
<string>Use for adding events to your calendar</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict>
</plist>
53 changes: 37 additions & 16 deletions app-ios/Sources/CommonComponents/Timetable/TimetableCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,24 @@ public struct TimetableCard: View {
let timetableItem: TimetableItem
let isFavorite: Bool
let onTap: (TimetableItem) -> Void
let onTapFavorite: (TimetableItem) -> Void
let onTapFavorite: (TimetableItem, CGPoint?) -> Void

public init(
timetableItem: TimetableItem,
isFavorite: Bool,
onTap: @escaping (TimetableItem) -> Void,
onTapFavorite: @escaping (TimetableItem) -> Void
onTapFavorite: @escaping (TimetableItem, CGPoint?) -> Void
) {
self.timetableItem = timetableItem
self.isFavorite = isFavorite
self.onTap = onTap
self.onTapFavorite = onTapFavorite
}

// MEMO: Used to adjust margins by Orientation.
@Environment(\.horizontalSizeClass) var heightSizeClass
@Environment(\.verticalSizeClass) var widthSizeClass

public var body: some View {
Button {
onTap(timetableItem)
Expand All @@ -35,20 +39,29 @@ public struct TimetableCard: View {
LanguageTag(label)
}
Spacer()
Button {
onTapFavorite(timetableItem)
} label: {
Image(isFavorite ? .icFavoriteFill : .icFavoriteOutline)
.resizable()
.renderingMode(.template)
.foregroundColor(
isFavorite ?
AssetColors.Primary.primaryFixed.swiftUIColor
:
AssetColors.Surface.onSurfaceVariant.swiftUIColor
)
.frame(width: 24, height: 24)

// [NOTE] In order to calculate the value from GeometryReader, it is supported by assigning DragGesture to the Image element instead of Button.
HStack {
GeometryReader { geometry in
// MEMO: Since the coordinate values ​​are based on the inside of the View, ".local" is specified.
let localGeometry = geometry.frame(in: .local)
Image(isFavorite ? .icFavoriteFill : .icFavoriteOutline)
.resizable()
.renderingMode(.template)
.foregroundColor(
isFavorite ? AssetColors.Primary.primaryFixed.swiftUIColor : AssetColors.Surface.onSurfaceVariant.swiftUIColor
)
.frame(width: 24, height: 24)
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global).onEnded { dragGesture in
// MEMO: The offset value in the Y-axis direction is subtracted for adjustment (decided by device orientation).
let adjustedLocationPoint = CGPoint(x: dragGesture.location.x, y: dragGesture.location.y - calculateTopMarginByDevideOrietation())
onTapFavorite(timetableItem, adjustedLocationPoint)
})
// MEMO: To adjust horizontal position, I'm subtracting half the size of Image (-12).
.position(x: localGeometry.maxX - 12, y: localGeometry.midY)
}
}
.frame(height: 24, alignment: .trailing)
.sensoryFeedback(.impact, trigger: isFavorite) { _, newValue in newValue }
}

Expand Down Expand Up @@ -85,6 +98,14 @@ public struct TimetableCard: View {
.overlay(RoundedRectangle(cornerRadius: 4).stroke(AssetColors.Outline.outlineVariant.swiftUIColor, lineWidth: 1))
}
}

private func calculateTopMarginByDevideOrietation() -> CGFloat {
if widthSizeClass == .regular && heightSizeClass == .compact {
return CGFloat(128)
} else {
return CGFloat(96)
}
}
}

#Preview {
Expand All @@ -93,7 +114,7 @@ public struct TimetableCard: View {
timetableItem: TimetableItem.Session.companion.fake(),
isFavorite: true,
onTap: { _ in },
onTapFavorite: { _ in }
onTapFavorite: { _,_ in }
)
.padding(.horizontal, 16)
}
Expand Down
49 changes: 49 additions & 0 deletions app-ios/Sources/ContributorFeature/ContributorsCountItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import SwiftUI
import Theme

struct ContributorsCountItem: View {
let totalContributor: Int
let duration: Double = 1.0
@State private var tracker = 0

var body: some View {
VStack(alignment: .leading) {

Text(String(localized: "Total", bundle: .module))
.textStyle(.titleMedium)
.foregroundStyle(AssetColors.Surface.onSurfaceVariant.swiftUIColor)
.frame(maxWidth: .infinity, alignment: .leading)

HStack {
Text("\(tracker)")
.textStyle(.headlineLarge)
.foregroundStyle(AssetColors.Surface.onSurface.swiftUIColor)
.onAppear() {
animate()
}

Text(String(localized: "Person", bundle: .module))
.textStyle(.headlineSmall)
.foregroundStyle(AssetColors.Surface.onSurface.swiftUIColor)
}

Spacer()
.frame(height: 16)
Divider()
}
}

func animate() {
let interval = duration / Double(totalContributor)
Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { time in
tracker += 1
if tracker == totalContributor {
time.invalidate()
}
}
}
}

#Preview {
ContributorsCountItem(totalContributor: 112)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ struct KmpPresenterContributorView: View {
if let existsState = state as? Exists {
ScrollView {
LazyVStack(spacing: 0) {

ContributorsCountItem(totalContributor: existsState.contributors.count)
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
.padding(.vertical, 10)

ForEach(existsState.contributors, id: \.id) { value in
let contributor = Model.Contributor(
id: Int(value.id),
Expand Down
Loading

0 comments on commit ae4e512

Please sign in to comment.