-
Notifications
You must be signed in to change notification settings - Fork 2
Tablet Client Application
This document covers the overall architecture, structure, and configuration of the Effective Office tablet client application. This is a Compose Multiplatform application that serves as the primary interface for office room management, allowing users to view room availability, create bookings, and manage meeting spaces.
For detailed information about specific application features, see Navigation & App Structure, Room Display & Slot Management, and Booking Features. For UI implementation details, see UI Components. For platform-specific configurations, see iOS Integration.
The tablet client is built using Kotlin Multiplatform with Compose Multiplatform for cross-platform UI development. Key technologies include:
Technology | Purpose | Version |
---|---|---|
Kotlin Multiplatform | Cross-platform development | 2.1.21 |
Compose Multiplatform | Declarative UI framework | 1.8.1 |
Decompose | Navigation and component management | Latest |
Koin | Dependency injection | Latest |
Kotlinx Coroutines | Asynchronous programming | Latest |
Firebase Messaging | Push notifications (Android) | 4.4.3 |
The navigation system uses Decompose for component-based navigation, with a main stack for primary screens and a slot navigation system for modal overlays.
The application is configured as a Kotlin Multiplatform project targeting both Android and iOS:
// Android Target
androidTarget()
// iOS Targets
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "ComposeApp"
isStatic = true
}
}
Module Category | Modules | Dependencies |
---|---|---|
Application | composeApp |
All feature and core modules |
Features |
feature:main , feature:bookingEditor , feature:fastBooking , feature:settings , feature:slot
|
Core modules only |
Core |
core:ui , core:domain , core:data
|
External libraries, no cross-dependencies |
The RootComponent
serves as the application's primary coordinator, managing:
-
Navigation State: Stack navigation between main screens and settings
-
Modal Management: Slot-based navigation for booking dialogs and overlays
-
Component Lifecycle: Creation and destruction of child components
-
Initial Configuration: Determines whether to show settings or main screen based on configuration
val childStack: Value<ChildStack<*, Child>> = childStack( source = navigation, initialConfiguration = if (checkSettingsUseCase().isEmpty()) { Config.Settings } else { Config.Main }, // ... )
The MainComponent
implements the primary business logic for room management:
State Property | Type | Purpose |
---|---|---|
roomList |
List<RoomInfo> |
Available rooms and their current status |
indexSelectRoom |
Int |
Currently selected room index |
selectedDate |
LocalDateTime |
Date for viewing/booking slots |
timeToNextEvent |
Int |
Minutes until next event in selected room |
isLoad/isData/isError |
Boolean |
UI state flags |
The component coordinates multiple use cases:
-
RoomInfoUseCase
: Fetches room data from backend -
UpdateUseCase
: Handles real-time updates via push notifications -
TimerUseCase
: Manages periodic UI updates -
DeleteBookingUseCase
: Handles event cancellation
The Android target includes specific configurations for tablet deployment:
-
Application ID:
band.effective.office.tablet
-
Deployment Mode: Kiosk mode support with
lockTaskMode="if_whitelisted"
- Firebase Integration: FCM service for push notifications
- Device Admin: Admin receiver for device management
The iOS framework exports key navigation and lifecycle components:
export(libs.decompose)
export(libs.decompose.compose.jetbrains)
export(libs.essenty.lifecycle)
export("com.mohamedrejeb.calf:calf-ui:0.8.0")
This enables the iOS app to integrate with the Kotlin Multiplatform framework while maintaining native iOS app structure.
The application uses a centralized settings system for configuration persistence:
class SettingsManager(private val settings: Settings) {
var currentRoomName: String
get() = settings.getString(KEY_NAME_ROOM, "")
private set(value) = settings.putString(KEY_NAME_ROOM, value)
fun updateSettings(newRoomName: String) {
currentRoomName = newRoomName
}
}
The settings determine the initial room selection and are used throughout the application for room-specific configurations.