Skip to content

Commit 55f3a2f

Browse files
author
code3-dev
committed
Add Download Options
1 parent 5d52e41 commit 55f3a2f

22 files changed

Lines changed: 284 additions & 35 deletions

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,58 @@
1-
# CCloud - Movie Streaming App
1+
# CCloud - Movie & TV Series Streaming App
22

3-
CCloud is a modern Android movie streaming application built with Jetpack Compose and Kotlin. The app provides a sleek user interface for browsing movies, playing videos, and customizing the viewing experience.
3+
<p align="center">
4+
<img src="app/src/main/res/drawable/splash_logo.png" alt="CCloud Logo" width="150"/>
5+
</p>
46

5-
## Features
7+
CCloud is a modern Android streaming application built with Jetpack Compose and Kotlin. The app provides a sleek user interface for browsing movies and TV series, playing videos, and customizing the viewing experience. With a focus on user experience and performance, CCloud delivers high-quality streaming content in an intuitive and visually appealing interface.
68

7-
- Browse movies with an attractive grid layout
8-
- View detailed information for each movie
9-
- Stream videos with a custom video player
10-
- Customize subtitle settings (background color, text color, border color, text size)
11-
- Theme customization (light/dark mode with color options)
12-
- Responsive UI with Material Design 3
9+
## 🚀 Key Features
1310

14-
## Tech Stack
11+
### 🎬 Content Discovery
12+
- **Browse Movies & Series**: Attractive grid layout for discovering content
13+
- **Powerful Search**: Search across both movies and TV series with real-time results
14+
- **Detailed Information**: Comprehensive details for each movie and series including ratings, genres, and descriptions
15+
16+
### ▶️ Media Playback
17+
- **Custom Video Player**: Built with ExoPlayer for smooth video playback
18+
- **Multiple Quality Options**: Choose from various quality options for playback and download
19+
- **Download Options**: Multiple download methods including browser, ADM, and VLC
20+
- **Fullscreen Experience**: Optimized landscape mode for immersive viewing
21+
22+
### 🎨 Personalization
23+
- **Theme Customization**: Light, dark, and system themes with color options
24+
- **Subtitle Settings**: Customize subtitle appearance (background, text color, border, size)
25+
- **Responsive UI**: Material Design 3 interface that adapts to all screen sizes
26+
27+
### 📱 User Experience
28+
- **Intuitive Navigation**: Bottom navigation for easy access to all sections
29+
- **Error Handling**: Retry mechanisms for failed requests
30+
- **Loading States**: Shimmer loading animations for smooth user experience
31+
- **Season & Episode Management**: Easy navigation through TV series seasons and episodes
32+
33+
## 🛠️ Tech Stack
1534

1635
- **Kotlin** - Primary programming language
1736
- **Jetpack Compose** - Modern toolkit for building native UI
1837
- **ExoPlayer** - Media playback library
1938
- **Kotlin Serialization** - JSON serialization
2039
- **Coil** - Image loading library
2140
- **Material Design 3** - UI components and design system
41+
- **Navigation Component** - For seamless screen transitions
42+
- **ViewModel & LiveData** - For state management
43+
- **Coroutines** - For asynchronous operations
44+
- **OkHttp** - For network requests
2245

23-
## Architecture
46+
## 🏗️ Architecture
2447

2548
The app follows a clean architecture pattern with the following components:
2649

27-
- **UI Layer** - Compose screens and components
28-
- **Data Layer** - Models and repositories
29-
- **Domain Layer** - Business logic
50+
- **UI Layer** - Jetpack Compose screens and components
51+
- **Data Layer** - Models and repositories for data management
52+
- **Domain Layer** - Business logic and use cases
3053
- **Utils** - Helper classes and extensions
54+
- **Navigation** - Single-activity architecture with Compose Navigation
55+
- **State Management** - ViewModel for UI state handling
3156

3257
## Getting Started
3358

@@ -98,29 +123,75 @@ Users can customize their experience through the settings screen:
98123
- Primary and secondary color selection
99124
- Subtitle settings (colors and text size)
100125

101-
### Navigation
126+
## 📱 App Screens
127+
128+
### 🎬 Movies Screen
129+
- Browse latest movies in an attractive grid layout
130+
- Pull-to-refresh functionality
131+
- Infinite scrolling for loading more content
132+
- Error handling with retry option
133+
- Shimmer loading animations
134+
135+
### 📺 Series Screen
136+
- Browse TV series with comprehensive information
137+
- Season and episode organization
138+
- Pull-to-refresh and infinite scrolling
139+
- Error handling with retry option
140+
141+
### 🔍 Search Screen
142+
- Real-time search across movies and series
143+
- Instant results as you type
144+
- Error handling with retry button
145+
- Clear search functionality
146+
147+
### 📄 Single Movie Screen
148+
- Detailed movie information
149+
- Multiple quality options for playback
150+
- Download options (Browser, ADM, VLC)
151+
- Custom video player integration
152+
153+
### 📺 Single Series Screen
154+
- Comprehensive series details
155+
- Season navigation and episode listing
156+
- Multiple quality options per episode
157+
- Download options for each episode
158+
- Error handling with retry functionality
159+
160+
### ⚙️ Settings Screen
161+
- Theme customization (Light/Dark/System)
162+
- Primary and secondary color selection
163+
- Subtitle settings (colors and text size)
164+
- Reset to default options
102165

166+
### 🏠 Bottom Navigation
103167
The app uses a bottom navigation bar to switch between:
104-
105168
- Movies screen
169+
- Series screen
106170
- Search screen
107171
- Settings screen
108-
- ...
109172

110-
## Contributing
173+
## 🤝 Contributing
174+
175+
We welcome contributions to CCloud! Here's how you can help:
111176

112177
1. Fork the repository
113178
2. Create a feature branch
114179
3. Commit your changes
115180
4. Push to the branch
116181
5. Create a pull request
117182

118-
## License
183+
Please ensure your code follows the existing style and includes appropriate tests.
184+
185+
## 📄 License
119186

120187
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
121188

122-
## Acknowledgments
189+
## 🙏 Acknowledgments
123190

124191
- [ExoPlayer](https://exoplayer.dev/) for media playback
125192
- [Coil](https://coil-kt.github.io/coil/) for image loading
126-
- [Material Design](https://m3.material.io/) for UI components
193+
- [Material Design](https://m3.material.io/) for UI components
194+
195+
## 📞 Contact
196+
197+
For support or inquiries, please open an issue on GitHub.

app/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ android {
2121

2222
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2323
}
24+
25+
buildFeatures {
26+
compose = true
27+
buildConfig = true // Add this line to enable BuildConfig generation
28+
}
2429

2530
signingConfigs {
2631
create("release") {

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
android:fullBackupContent="@xml/backup_rules"
1313
android:icon="@mipmap/ic_launcher"
1414
android:label="@string/app_name"
15-
android:roundIcon="@mipmap/ic_launcher_round"
1615
android:supportsRtl="false"
1716
android:theme="@style/Theme.CCloud"
1817
android:usesCleartextTraffic="true"

app/src/main/java/com/pira/ccloud/MainActivity.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ fun MainScreen(onThemeSettingsChanged: (ThemeSettings) -> Unit = {}) {
106106
Scaffold(
107107
modifier = Modifier.fillMaxSize(),
108108
topBar = {
109-
// Only show top bar if the current screen requires it
110-
if (currentScreen.showBottomBar) {
109+
// Only show top bar if the current screen requires it and we're not on splash
110+
if (currentScreen.showBottomBar && currentRoute != AppScreens.Splash.route) {
111111
AnimatedContent(
112112
targetState = currentScreen,
113113
transitionSpec = {
@@ -134,8 +134,8 @@ fun MainScreen(onThemeSettingsChanged: (ThemeSettings) -> Unit = {}) {
134134
}
135135
},
136136
bottomBar = {
137-
// Only show bottom bar if the current screen requires it
138-
if (currentScreen.showBottomBar) {
137+
// Only show bottom bar if the current screen requires it and we're not on splash
138+
if (currentScreen.showBottomBar && currentRoute != AppScreens.Splash.route) {
139139
BottomNavigationBar(navController)
140140
}
141141
}

app/src/main/java/com/pira/ccloud/navigation/AppNavigation.kt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,38 @@ import com.pira.ccloud.screens.SeriesScreen
1111
import com.pira.ccloud.screens.SettingsScreen
1212
import com.pira.ccloud.screens.SingleMovieScreen
1313
import com.pira.ccloud.screens.SingleSeriesScreen
14+
import com.pira.ccloud.screens.SplashScreen
1415
import com.pira.ccloud.ui.theme.ThemeSettings
16+
import com.pira.ccloud.ui.theme.ThemeManager
17+
import androidx.compose.ui.platform.LocalContext
1518

1619
@Composable
1720
fun AppNavigation(
1821
navController: NavHostController,
1922
onThemeSettingsChanged: (ThemeSettings) -> Unit = {}
2023
) {
24+
val context = LocalContext.current
25+
val themeManager = ThemeManager(context)
26+
val themeSettings = themeManager.loadThemeSettings()
27+
2128
NavHost(
2229
navController = navController,
23-
startDestination = AppScreens.Movies.route
30+
startDestination = AppScreens.Splash.route
2431
) {
32+
composable(route = AppScreens.Splash.route) {
33+
SplashScreen(
34+
onTimeout = {
35+
navController.popBackStack()
36+
navController.navigate(AppScreens.Movies.route)
37+
},
38+
backgroundColor = if (themeSettings.themeMode == com.pira.ccloud.ui.theme.ThemeMode.DARK) {
39+
androidx.compose.ui.graphics.Color(0xFF121212)
40+
} else {
41+
androidx.compose.ui.graphics.Color(0xFFFFFBFE)
42+
}
43+
)
44+
}
45+
2546
composable(route = AppScreens.Movies.route) {
2647
MoviesScreen(navController = navController)
2748
}

app/src/main/java/com/pira/ccloud/navigation/AppScreens.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@ import com.pira.ccloud.R
1212
sealed class AppScreens(
1313
val route: String,
1414
@StringRes val resourceId: Int,
15-
val icon: ImageVector,
15+
val icon: ImageVector? = null,
1616
val showBottomBar: Boolean = true
1717
) {
18+
data object Splash : AppScreens(
19+
route = "splash",
20+
resourceId = R.string.app_name
21+
)
22+
1823
data object Movies : AppScreens(
1924
route = "movies",
2025
resourceId = R.string.movies,

app/src/main/java/com/pira/ccloud/navigation/BottomNavigation.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import androidx.compose.foundation.layout.height
1111
import androidx.compose.foundation.layout.padding
1212
import androidx.compose.foundation.layout.size
1313
import androidx.compose.foundation.shape.CircleShape
14+
import androidx.compose.material.icons.Icons
15+
import androidx.compose.material.icons.filled.Movie
1416
import androidx.compose.material3.Icon
1517
import androidx.compose.material3.NavigationBar
1618
import androidx.compose.material3.NavigationBarItem
@@ -81,7 +83,7 @@ fun BottomNavigationBar(navController: NavController) {
8183
) {}
8284
}
8385
Icon(
84-
imageVector = screen.icon,
86+
imageVector = screen.icon ?: Icons.Default.Movie, // Provide a fallback icon
8587
contentDescription = stringResource(screen.resourceId),
8688
tint = iconColor,
8789
modifier = Modifier.size(24.dp)

app/src/main/java/com/pira/ccloud/screens/SearchScreen.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import androidx.compose.material.icons.Icons
3232
import androidx.compose.material.icons.filled.Clear
3333
import androidx.compose.material.icons.filled.Search
3434
import androidx.compose.material.icons.filled.Star
35+
import androidx.compose.material3.Button
3536
import androidx.compose.material3.Card
3637
import androidx.compose.material3.CardDefaults
3738
import androidx.compose.material3.CircularProgressIndicator
@@ -171,6 +172,13 @@ fun SearchScreen(
171172
style = MaterialTheme.typography.bodyMedium,
172173
color = MaterialTheme.colorScheme.onSurfaceVariant
173174
)
175+
Spacer(modifier = Modifier.height(16.dp))
176+
Button(
177+
onClick = { viewModel.updateSearchQuery(viewModel.searchQuery) },
178+
modifier = Modifier.padding(16.dp)
179+
) {
180+
Text("Retry")
181+
}
174182
}
175183
}
176184
}

app/src/main/java/com/pira/ccloud/screens/SingleSeriesScreen.kt

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -650,12 +650,26 @@ fun SeriesDetailsContent(
650650
modifier = Modifier.padding(16.dp)
651651
)
652652
} else if (seasonsViewModel.errorMessage != null) {
653-
Text(
654-
text = "Error loading seasons: ${seasonsViewModel.errorMessage}",
655-
style = MaterialTheme.typography.bodyMedium,
656-
color = MaterialTheme.colorScheme.error,
657-
modifier = Modifier.padding(16.dp)
658-
)
653+
Column(
654+
modifier = Modifier
655+
.fillMaxWidth()
656+
.padding(16.dp),
657+
horizontalAlignment = Alignment.CenterHorizontally
658+
) {
659+
Text(
660+
text = "Error loading seasons: ${seasonsViewModel.errorMessage}",
661+
style = MaterialTheme.typography.bodyMedium,
662+
color = MaterialTheme.colorScheme.error,
663+
modifier = Modifier.padding(16.dp)
664+
)
665+
Spacer(modifier = Modifier.height(16.dp))
666+
Button(
667+
onClick = { seasonsViewModel.loadSeasons(series.id) },
668+
modifier = Modifier.padding(16.dp)
669+
) {
670+
Text("Retry")
671+
}
672+
}
659673
} else if (seasonsViewModel.seasons.isNotEmpty()) {
660674
val selectedSeason = seasonsViewModel.seasons[selectedSeasonIndex]
661675
Column {

0 commit comments

Comments
 (0)