Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat Starter Kit #1

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,54 @@
# starter-for-android
Appwrite's starter kit for Android 🤖
# Android Starter Kit with Appwrite

Kickstart your Android development with this ready-to-use starter project integrated
with [Appwrite](https://appwrite.io).

This guide will help you quickly set up, customize, and build your Android app using **Jetpack
Compose**.

---

## 🚀 Getting Started

### Clone the Project

Clone this repository to your local machine using Git or directly from `Android Studio`:

```bash
git clone https://github.com/appwrite/starter-for-android
```

Alternatively, open the repository URL in `Android Studio` to clone it directly.

---

## 🛠️ Development Guide

1. **Configure Appwrite**
Navigate to `data/repository/AppwriteRepository.kt` and update the values to match your Appwrite
project credentials.

2. **Customize as Needed**
Modify the starter kit to suit your app's requirements. Adjust UI, features, or backend
integrations as per your needs.

3. **Run the App**
Select a target device (emulator or connected physical Android device) in `Android Studio`, and
click **Run** to start the app.

---

## 📦 Building for Production

To create a production build of your app:

1. Open **Build variants** > **app** in the menu bar.
2. Choose **release**
3. Build and deploy your app in release mode.

---

## 💡 Additional Notes

- This starter project is designed to streamline your Android development with Appwrite.
- Refer to the [Appwrite Documentation](https://appwrite.io/docs) for detailed integration guidance.
10 changes: 10 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.iml
.gradle
.idea
build
gradle
local.properties
.externalNativeBuild

/captures
.DS_Store
68 changes: 68 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}

android {
namespace = "io.appwrite.starterkit"
compileSdk = 35

defaultConfig {
minSdk = 21
targetSdk = 35
versionCode = 1
versionName = "1.0"
applicationId = "io.appwrite.starterkit"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

kotlinOptions {
jvmTarget = "11"
}

buildFeatures {
compose = true
}
}

dependencies {
// appwrite
implementation(libs.appwrite)

// splashscreen
implementation(libs.androidx.core.splashscreen)

// core, compose and runtime
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.viewmodel.compose)

// ui, preview & material
implementation(libs.androidx.ui)
implementation(libs.androidx.material3)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)

// compose platform
implementation(platform(libs.androidx.compose.bom))

// debug libraries
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
24 changes: 24 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="AppwriteStarterKit"
android:supportsRtl="true"
android:theme="@style/Theme.AppwriteStarterKit.SplashTheme"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
138 changes: 138 additions & 0 deletions app/src/main/java/io/appwrite/starterkit/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package io.appwrite.starterkit

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.RestrictTo
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import io.appwrite.starterkit.data.models.Status
import io.appwrite.starterkit.data.models.mockProjectInfo
import io.appwrite.starterkit.extensions.copy
import io.appwrite.starterkit.extensions.edgeToEdgeWithStyle
import io.appwrite.starterkit.ui.components.CollapsibleBottomSheet
import io.appwrite.starterkit.ui.components.ConnectionStatusView
import io.appwrite.starterkit.ui.components.GettingStartedCards
import io.appwrite.starterkit.ui.components.TopPlatformView
import io.appwrite.starterkit.ui.components.addCheckeredBackground
import io.appwrite.starterkit.ui.theme.AppwriteStarterKitTheme
import io.appwrite.starterkit.viewmodels.AppwriteViewModel
import kotlinx.coroutines.delay

/**
* MainActivity serves as the entry point for the application.
* It configures the system's edge-to-edge settings, splash screen, and initializes the composable layout.
*/
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)

edgeToEdgeWithStyle()
WindowCompat.setDecorFitsSystemWindows(window, false)

setContent { AppwriteStarter() }
}
}

/**
* AppwriteStarter is the root composable function that sets up the main UI layout.
* It manages the logs, status, and project information using the provided [AppwriteViewModel].
*/
@Composable
fun AppwriteStarter(
viewModel: AppwriteViewModel = viewModel(),
) {
val logs by viewModel.logs.collectAsState()
val status by viewModel.status.collectAsState()

// data doesn't change, so no `remember`.
val projectInfo = viewModel.getProjectInfo()

AppwriteStarterKitTheme {
Scaffold(bottomBar = {
CollapsibleBottomSheet(
logs = logs,
projectInfo = projectInfo
)
}) { innerPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.addCheckeredBackground()
.padding(innerPadding.copy(top = 16.dp, bottom = 0.dp))
.windowInsetsPadding(WindowInsets.systemBars)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
TopPlatformView(
status = status
)

ConnectionStatusView(status) {
viewModel.ping()
}

GettingStartedCards()
}
}
}
}

@Preview
@Composable
@RestrictTo(RestrictTo.Scope.TESTS)
private fun AppwriteStarterPreview() {
val status = remember { mutableStateOf<Status>(Status.Idle) }

AppwriteStarterKitTheme {
Scaffold(bottomBar = {
CollapsibleBottomSheet(
logs = emptyList(),
projectInfo = mockProjectInfo
)
}) { innerPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.addCheckeredBackground()
.padding(innerPadding.copy(top = 16.dp, bottom = 0.dp))
.windowInsetsPadding(WindowInsets.systemBars)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
TopPlatformView(
status = status.value
)

ConnectionStatusView(status.value) {
// simulate a success ping
status.value = Status.Loading
delay(1000)
status.value = Status.Success
}

GettingStartedCards()
}
}
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/io/appwrite/starterkit/data/models/Log.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.appwrite.starterkit.data.models

/**
* A data model for holding log entries.
*/
data class Log(
val date: String,
val status: String,
val method: String,
val path: String,
val response: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.appwrite.starterkit.data.models

import androidx.annotation.RestrictTo

/**
* A data model for holding appwrite project information.
*/
data class ProjectInfo(
val endpoint: String,
val projectId: String,
val projectName: String,
val version: String,
)

/**
* A mock `ProjectInfo` model, just for **previews**.
*/
@RestrictTo(RestrictTo.Scope.TESTS)
internal val mockProjectInfo = ProjectInfo(
endpoint = "https://mock.api/v1",
projectId = "sample-project-id",
projectName = "AppwriteStarter",
version = "1.6.0",
)
27 changes: 27 additions & 0 deletions app/src/main/java/io/appwrite/starterkit/data/models/Status.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.appwrite.starterkit.data.models

/**
* Represents the various states of a process or operation.
* This sealed class ensures that only predefined statuses are used.
*/
sealed class Status {
/**
* Represents the idle state.
*/
data object Idle : Status()

/**
* Represents a loading state.
*/
data object Loading : Status()

/**
* Represents a successful operation.
*/
data object Success : Status()

/**
* Represents an error state.
*/
data object Error : Status()
}
Loading