1
0
Fork 0
mirror of synced 2024-06-25 17:50:38 +12:00

feat: added iOS platform to origin validator

This commit is contained in:
Christy Jacob 2021-06-11 12:44:30 +05:30
parent c981ff39c0
commit 43d9c416a3
174 changed files with 5169 additions and 80 deletions

View file

@ -0,0 +1,53 @@
name: Publish to Maven Central
# Run this workflow when a release is created
on:
release:
types: [released]
jobs:
publish:
name: Release build and publish
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
# Base64 decodes and pipes the GPG key content into the secret file
- name: Prepare environment
env:
GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY_CONTENTS }}
SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }}
run: |
git fetch --unshallow
sudo bash -c "echo '$GPG_KEY_CONTENTS' | base64 -d > '$SIGNING_SECRET_KEY_RING_FILE'"
chmod +x ./gradlew
# Builds the release artifacts of the library
- name: Build Release Artifacts
run: ./gradlew --info library:assembleRelease
# Generates other artifacts (javadocJar is optional)
- name: Generate Source jar
run: ./gradlew javadocJar
# Runs upload, and then closes & releases the repository
- name: Publish Release Version to MavenCentral
run: |
if ${{ endswith(github.event.release.tag_name, '-SNAPSHOT') }}; then
echo "Publising Snapshot Version ${{ github.event.release.tag_name}} to Snapshot repository"
./gradlew publishReleasePublicationToSonatypeRepository
else
echo "Publising Release Version ${{ github.event.release.tag_name}} to Staging repository"
./gradlew publishReleasePublicationToSonatypeRepository --max-workers 1 closeAndReleaseSonatypeStagingRepository
fi
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }}
SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }}

12
app/sdks/client-android/.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
*.iml
.gradle
/local.properties
/.idea/*
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
.local.properties
.env
*/build

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1,12 @@
Copyright (c) 2021 Appwrite (https://appwrite.io) and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name Appwrite nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,157 @@
# Appwrite Android SDK
![License](https://img.shields.io/github/license/appwrite/sdk-for-android.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-0.8.0-blue.svg?style=flat-square)
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite_io?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite_io)
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord)
**This SDK is compatible with Appwrite server version 0.8.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-android/releases).**
Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Android SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
![Appwrite](https://appwrite.io/images/github.png)
## Installation
### Gradle
Appwrite's Android SDK is hosted on Maven Central. In order to fetch the Appwrite SDK, add this to your root level `build.gradle(.kts)` file:
```groovy
repositories {
mavenCentral()
}
```
If you would like to fetch our SNAPSHOT releases, you need to add the SNAPSHOT maven repository to your `build.gradle(.kts)`:
```groovy
repositories {
maven {
url "https://s01.oss.sonatype.org/content/repositories/snapshots/"
}
}
```
Next, add the dependency to your project's `build.gradle(.kts)` file:
```groovy
implementation("io.appwrite:sdk-for-android:0.0.0-SNAPSHOT")
```
### Maven
Add this to your project's `pom.xml` file:
```xml
<dependencies>
<dependency>
<groupId>io.appwrite</groupId>
<artifactId>sdk-for-android</artifactId>
<version>0.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
```
## Getting Started
### Add your Android Platform
To initialize your SDK and start interacting with Appwrite services, you need to add a new Android platform to your project. To add a new platform, go to your Appwrite console, select your project (create one if you haven't already), and click the 'Add Platform' button on the project Dashboard.
From the options, choose to add a new **Android** platform and add your app credentials.
Add your app <u>name</u> and <u>package name</u>. Your package name is generally the applicationId in your app-level `build.gradle` file. By registering a new platform, you are allowing your app to communicate with the Appwrite API.
### Registering additional activities
In order to capture the Appwrite OAuth callback url, the following activity needs to be added to your [AndroidManifest.xml](https://github.com/appwrite/playground-for-android/blob/master/app/src/main/AndroidManifest.xml). Be sure to replace the **[PROJECT_ID]** string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in the console.
```xml
<manifest>
<application>
<activity android:name="io.appwrite.views.CallbackActivity" >
<intent-filter android:label="android_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appwrite-callback-[PROJECT_ID]" />
</intent-filter>
</activity>
</application>
</manifest>
```
### Init your SDK
<p>Initialize your SDK with your Appwrite server API endpoint and project ID, which can be found in your project settings page.
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setSelfSigned(true) // Remove in production
```
Before starting to send any API calls to your new Appwrite instance, make sure your Android emulators has network access to the Appwrite server hostname or IP address.
When trying to connect to Appwrite from an emulator or a mobile device, localhost is the hostname of the device or emulator and not your local Appwrite instance. You should replace localhost with your private IP. You can also use a service like [ngrok](https://ngrok.com/) to proxy the Appwrite API.
### Make Your First Request
<p>Once your SDK object is set, access any of the Appwrite services and choose any request to send. Full documentation for any service method you would like to use can be found in your SDK documentation or in the [API References](https://appwrite.io/docs) section.
```kotlin
// Register User
val account = Account(client)
val response = account.create(
"email@example.com",
"password"
)
```
### Full Example
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setSelfSigned(true) // Remove in production
val account = Account(client)
val response = account.create(
"email@example.com",
"password"
)
```
### Error Handling
The Appwrite Android SDK raises an `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
```kotlin
try {
var response = account.create("email@example.com", "password")
Log.d("Appwrite response", response.body?.string())
} catch(e : AppwriteException) {
Log.e("AppwriteException",e.message.toString())
}
```
### Learn more
You can use following resources to learn more and get help
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-android)
- 📜 [Appwrite Docs](https://appwrite.io/docs)
- 💬 [Discord Community](https://appwrite.io/discord)
- 🚂 [Appwrite Android Playground](https://github.com/appwrite/playground-for-android)
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -0,0 +1,36 @@
apply plugin: 'io.github.gradle-nexus.publish-plugin'
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.4.31"
version '0.0.0-SNAPSHOT'
repositories {
maven { url "https://plugins.gradle.org/m2/" }
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'io.github.gradle-nexus:publish-plugin:1.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven { url "https://jitpack.io" }
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
apply from: "${rootDir}/scripts/publish-config.gradle"

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.createAnonymousSession()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.createJWT()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.createOAuth2Session("amazon")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.createRecovery("email@example.com", "https://example.com")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.createSession("email@example.com", "password")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.createVerification("https://example.com")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.create("email@example.com", "password")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.deleteSession("[SESSION_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.deleteSessions()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.delete()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.getLogs()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.getPrefs()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.getSessions()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.get()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.updateEmail("email@example.com", "password")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.updateName("[NAME]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.updatePassword("password")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.updatePrefs({})
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.updateRecovery("[USER_ID]", "[SECRET]", "password", "password")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val accountService = Account(client)
val response = accountService.updateVerification("[USER_ID]", "[SECRET]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Avatars
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val avatarsService = Avatars(client)
val response = avatarsService.getBrowser("aa")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Avatars
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val avatarsService = Avatars(client)
val response = avatarsService.getCreditCard("amex")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Avatars
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val avatarsService = Avatars(client)
val response = avatarsService.getFavicon("https://example.com")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Avatars
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val avatarsService = Avatars(client)
val response = avatarsService.getFlag("af")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Avatars
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val avatarsService = Avatars(client)
val response = avatarsService.getImage("https://example.com")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Avatars
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val avatarsService = Avatars(client)
val response = avatarsService.getInitials()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Avatars
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val avatarsService = Avatars(client)
val response = avatarsService.getQR("[TEXT]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Database
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val databaseService = Database(client)
val response = databaseService.createDocument("[COLLECTION_ID]", {})
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Database
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val databaseService = Database(client)
val response = databaseService.deleteDocument("[COLLECTION_ID]", "[DOCUMENT_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Database
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val databaseService = Database(client)
val response = databaseService.getDocument("[COLLECTION_ID]", "[DOCUMENT_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Database
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val databaseService = Database(client)
val response = databaseService.listDocuments("[COLLECTION_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Database
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val databaseService = Database(client)
val response = databaseService.updateDocument("[COLLECTION_ID]", "[DOCUMENT_ID]", {})
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Functions
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val functionsService = Functions(client)
val response = functionsService.createExecution("[FUNCTION_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Functions
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val functionsService = Functions(client)
val response = functionsService.getExecution("[FUNCTION_ID]", "[EXECUTION_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Functions
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val functionsService = Functions(client)
val response = functionsService.listExecutions("[FUNCTION_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Locale
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val localeService = Locale(client)
val response = localeService.getContinents()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Locale
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val localeService = Locale(client)
val response = localeService.getCountriesEU()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Locale
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val localeService = Locale(client)
val response = localeService.getCountriesPhones()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Locale
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val localeService = Locale(client)
val response = localeService.getCountries()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Locale
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val localeService = Locale(client)
val response = localeService.getCurrencies()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Locale
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val localeService = Locale(client)
val response = localeService.getLanguages()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Locale
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val localeService = Locale(client)
val response = localeService.get()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.createFile(new File("./path-to-files/image.jpg"))
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.deleteFile("[FILE_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.getFileDownload("[FILE_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.getFilePreview("[FILE_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.getFileView("[FILE_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.getFile("[FILE_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.listFiles()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Storage
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val storageService = Storage(client)
val response = storageService.updateFile("[FILE_ID]", List<Any>(), List<Any>())
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.createMembership("[TEAM_ID]", "email@example.com", List<Any>(), "https://example.com")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.create("[NAME]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.deleteMembership("[TEAM_ID]", "[MEMBERSHIP_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.delete("[TEAM_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.getMemberships("[TEAM_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.get("[TEAM_ID]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.list()
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.updateMembershipRoles("[TEAM_ID]", "[MEMBERSHIP_ID]", List<Any>())
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.updateMembershipStatus("[TEAM_ID]", "[MEMBERSHIP_ID]", "[USER_ID]", "[SECRET]")
val json = response.body?.string()

View file

@ -0,0 +1,10 @@
import io.appwrite.Client
import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val teamsService = Teams(client)
val response = teamsService.update("[TEAM_ID]", "[NAME]")
val json = response.body?.string()

View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,59 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "io.appwrite.android"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
dataBinding true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation project(path: ':library')
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation "androidx.fragment:fragment-ktx:1.3.2"
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3"
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.appwrite.android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppwriteAndroidSDK">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,23 @@
package io.appwrite.android
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.add
import androidx.fragment.app.commit
import io.appwrite.android.ui.accounts.AccountsFragment
import io.appwrite.android.utils.Client
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Client.create(applicationContext)
if (savedInstanceState == null) {
supportFragmentManager.commit {
setReorderingAllowed(true)
add<AccountsFragment>(R.id.fragment_container_view)
}
}
}
}

View file

@ -0,0 +1,69 @@
package io.appwrite.android.ui.accounts
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import io.appwrite.android.R
import io.appwrite.android.databinding.FragmentAccountBinding
class AccountsFragment : Fragment() {
private lateinit var binding: FragmentAccountBinding
private lateinit var viewModel: AccountsViewModel
override fun onCreateView(
inflater: LayoutInflater ,
container: ViewGroup? ,
savedInstanceState: Bundle?
): View? {
viewModel = ViewModelProvider(this).get(AccountsViewModel::class.java)
binding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_account,
container,
false
)
binding.lifecycleOwner = viewLifecycleOwner
binding.login.setOnClickListener{
viewModel.onLogin(binding.email.text, binding.password.text)
}
binding.signup.setOnClickListener{
viewModel.onSignup(binding.email.text, binding.password.text, binding.name.text)
}
binding.getUser.setOnClickListener{
viewModel.getUser()
}
binding.oAuth.setOnClickListener{
viewModel.oAuthLogin(activity as ComponentActivity)
}
binding.logout.setOnClickListener{
viewModel.logout()
}
viewModel.error.observe(viewLifecycleOwner, Observer { event ->
event?.getContentIfNotHandled()?.let { // Only proceed if the event has never been handled
Toast.makeText(requireContext(), it.message , Toast.LENGTH_SHORT).show()
}
})
viewModel.response.observe(viewLifecycleOwner, Observer { event ->
event?.getContentIfNotHandled()?.let {
binding.responseTV.setText(it)
}
})
return binding.root
}
}

View file

@ -0,0 +1,96 @@
package io.appwrite.android.ui.accounts
import android.text.Editable
import androidx.activity.ComponentActivity
import androidx.lifecycle.*
import io.appwrite.android.utils.Client.client
import io.appwrite.android.utils.Event
import io.appwrite.exceptions.AppwriteException
import io.appwrite.services.Account
import kotlinx.coroutines.launch
import org.json.JSONObject
class AccountsViewModel : ViewModel() {
private val _error = MutableLiveData<Event<Exception>>().apply {
value = null
}
val error: LiveData<Event<Exception>> = _error
private val _response = MutableLiveData<Event<String>>().apply {
value = null
}
val response: LiveData<Event<String>> = _response
private val accountService by lazy {
Account(client)
}
fun onLogin(email: Editable , password : Editable) {
viewModelScope.launch {
try {
var response = accountService.createSession(email.toString(), password.toString())
var json = response.body?.string() ?: ""
json = JSONObject(json).toString(8)
_response.postValue(Event(json))
} catch (e: AppwriteException) {
_error.postValue(Event(e))
}
}
}
fun onSignup(email: Editable , password : Editable, name: Editable) {
viewModelScope.launch {
try {
var response = accountService.create(email.toString(), password.toString(), name.toString())
var json = response.body?.string() ?: ""
json = JSONObject(json).toString(2)
_response.postValue(Event(json))
} catch (e: AppwriteException) {
_error.postValue(Event(e))
}
}
}
fun oAuthLogin(activity: ComponentActivity) {
viewModelScope.launch {
try {
accountService.createOAuth2Session(activity, "facebook", "appwrite-callback-6070749e6acd4://demo.appwrite.io/auth/oauth2/success", "appwrite-callback-6070749e6acd4://demo.appwrite.io/auth/oauth2/failure")
} catch (e: Exception) {
_error.postValue(Event(e))
} catch (e: AppwriteException) {
_error.postValue(Event(e))
}
}
}
fun getUser() {
viewModelScope.launch {
try {
var response = accountService.get()
var json = response.body?.string() ?: ""
json = JSONObject(json).toString(2)
_response.postValue(Event(json))
} catch (e: AppwriteException) {
_error.postValue(Event(e))
}
}
}
fun logout() {
viewModelScope.launch {
try {
var response = accountService.deleteSession("current")
var json = response.body?.string()?.ifEmpty { "{}" }
json = JSONObject(json).toString(4)
_response.postValue(Event(json))
} catch (e: AppwriteException) {
_error.postValue(Event(e))
}
}
}
}

View file

@ -0,0 +1,20 @@
package io.appwrite.android.utils
import android.content.Context
import io.appwrite.Client
object Client {
lateinit var client : Client
fun create(context: Context) {
client = Client(context)
.setEndpoint("https://demo.appwrite.io/v1")
.setProject("6070749e6acd4")
/* Useful when testing locally */
// client = Client(context)
// .setEndpoint("https://192.168.1.35/v1")
// .setProject("60bdbc911784e")
// .setSelfSigned(true)
}
}

View file

@ -0,0 +1,27 @@
package io.appwrite.android.utils
/**
* Used as a wrapper for data that is exposed via a LiveData that represents an event.
*/
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}

View file

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View file

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraint_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<EditText
android:id="@+id/responseTV"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@null"
android:enabled="true"
android:fadeScrollbars="false"
android:focusable="true"
android:longClickable="true"
android:scrollbars="vertical"
android:textIsSelectable="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Email"
android:inputType="textEmailAddress"
android:text="test@test.com"
app:layout_constraintStart_toStartOf="@id/responseTV"
app:layout_constraintTop_toBottomOf="@id/responseTV" />
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="password"
android:inputType="textPassword"
android:text="testtest"
app:layout_constraintStart_toStartOf="@id/email"
app:layout_constraintTop_toBottomOf="@id/email" />
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="name"
android:inputType="text"
app:layout_constraintStart_toStartOf="@id/password"
app:layout_constraintTop_toBottomOf="@id/password" />
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Login"
app:layout_constraintEnd_toStartOf="@+id/signup"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/name" />
<Button
android:id="@+id/signup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Signup"
app:layout_constraintEnd_toStartOf="@id/getUser"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/login"
app:layout_constraintTop_toBottomOf="@+id/name" />
<Button
android:id="@+id/getUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Get User"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/signup"
app:layout_constraintTop_toBottomOf="@+id/name" />
<Button
android:id="@+id/oAuth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Login with Facebook"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@+id/logout"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/signup" />
<Button
android:id="@+id/logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Logout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/oAuth"
app:layout_constraintTop_toTopOf="@id/oAuth" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</layout>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View file

@ -0,0 +1,3 @@
<resources>
<string name="app_name">Appwrite Android SDK</string>
</resources>

View file

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.AppwriteAndroidSDK" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View file

@ -0,0 +1,19 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official

Binary file not shown.

View file

@ -0,0 +1,6 @@
#Tue Jun 01 15:55:54 IST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

172
app/sdks/client-android/gradlew vendored Normal file
View file

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
app/sdks/client-android/gradlew.bat vendored Normal file
View file

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,77 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
plugins {
id("com.android.library")
id("kotlin-android")
}
ext {
PUBLISH_GROUP_ID = 'io.appwrite'
PUBLISH_ARTIFACT_ID = 'sdk-for-android'
PUBLISH_VERSION = '0.0.0-SNAPSHOT'
POM_URL = ''
POM_SCM_URL = 'https://github.com/appwrite/sdk-for-android'
POM_ISSUE_URL = 'https://github.com/appwrite/sdk-for-android/issues'
POM_DESCRIPTION = 'Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Android SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)'
POM_LICENSE_URL = 'https://opensource.org/licenses/GPL-3.0'
POM_LICENSE_NAME = "GPL-3.0"
POM_DEVELOPER_ID = ''
POM_DEVELOPER_NAME = 'appwrite'
POM_DEVELOPER_EMAIL = ''
GITHUB_SCM_CONNECTION = 'scm:git:git://github.com/appwrite/sdk-for-android.git'
}
android {
compileSdkVersion(30)
defaultConfig {
minSdkVersion(21)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
named("release") {
minifyEnabled false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${KotlinCompilerVersion.VERSION}")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
api("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3")
api(platform("com.squareup.okhttp3:okhttp-bom:4.9.0"))
api("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:okhttp-urlconnection")
implementation("com.squareup.okhttp3:logging-interceptor")
implementation("com.google.code.gson:gson:2.8.5")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1")
implementation("androidx.lifecycle:lifecycle-common-java8:2.3.1")
implementation("androidx.appcompat:appcompat:1.2.0")
implementation("androidx.fragment:fragment-ktx:1.3.2")
implementation("androidx.activity:activity-ktx:1.2.2")
implementation("androidx.browser:browser:1.3.0")
implementation("com.github.franmontiel:PersistentCookieJar:v1.0.1")
testImplementation 'junit:junit:4.+'
}
apply from: "${rootProject.projectDir}/scripts/publish-module.gradle"

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="io.appwrite.appwrite">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View file

@ -0,0 +1,259 @@
package io.appwrite
import android.content.Context
import android.content.pm.PackageManager
import com.franmontiel.persistentcookiejar.ClearableCookieJar
import com.franmontiel.persistentcookiejar.PersistentCookieJar
import com.franmontiel.persistentcookiejar.cache.SetCookieCache
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor
import com.google.gson.Gson
import io.appwrite.exceptions.AppwriteException
import io.appwrite.extensions.JsonExtensions.fromJson
import io.appwrite.models.Error
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.*
import okhttp3.Headers.Companion.toHeaders
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.logging.HttpLoggingInterceptor
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
class Client(
context: Context,
var endPoint: String = "https://appwrite.io/v1",
private var selfSigned: Boolean = false
) : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
private val job = Job()
private lateinit var http: OkHttpClient
private val headers: MutableMap<String, String>
val config: MutableMap<String, String>
val cookieJar: ClearableCookieJar = PersistentCookieJar(
SetCookieCache(),
SharedPrefsCookiePersistor(context)
)
val appVersion by lazy {
try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
return@lazy pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
return@lazy ""
}
}
init {
headers = mutableMapOf(
"content-type" to "application/json",
"origin" to "appwrite-android://${context.packageName}",
"user-agent" to "${context.packageName}/${appVersion}, ${System.getProperty("http.agent")}",
"x-sdk-version" to "appwrite:kotlin:0.0.0-SNAPSHOT",
"x-appwrite-response-format" to "0.8.0"
)
config = mutableMapOf()
setSelfSigned(selfSigned)
}
/// Your project ID
fun setProject(value: String): Client {
config["project"] = value
addHeader("x-appwrite-project", value)
return this
}
/// Your secret JSON Web Token
fun setJWT(value: String): Client {
config["jWT"] = value
addHeader("x-appwrite-jwt", value)
return this
}
fun setLocale(value: String): Client {
config["locale"] = value
addHeader("x-appwrite-locale", value)
return this
}
fun setSelfSigned(status: Boolean): Client {
selfSigned = status
val builder = OkHttpClient()
.newBuilder()
.cookieJar(cookieJar)
.addInterceptor(HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BODY) })
if (!selfSigned) {
http = builder.build()
return this
}
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts = arrayOf<TrustManager>(
object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
}
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
}
)
// Install the all-trusting trust manager
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, SecureRandom())
// Create an ssl socket factory with our all-trusting manager
val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
builder.hostnameVerifier(HostnameVerifier { _, _ -> true })
http = builder.build()
} catch (e: Exception) {
throw RuntimeException(e)
}
return this
}
fun setEndpoint(endPoint: String): Client {
this.endPoint = endPoint
return this
}
fun addHeader(key: String, value: String): Client {
headers[key] = value
return this
}
@Throws(AppwriteException::class)
suspend fun call(
method: String,
path: String,
headers: Map<String, String> = mapOf(),
params: Map<String, Any?> = mapOf()
): Response {
val requestHeaders = this.headers.toHeaders().newBuilder()
.addAll(headers.toHeaders())
.build()
val httpBuilder = (endPoint + path).toHttpUrl().newBuilder()
if ("GET" == method) {
params.forEach {
when (it.value) {
null -> {
return@forEach
}
is List<*> -> {
httpBuilder.addQueryParameter(it.key + "[]", it.value.toString())
}
else -> {
httpBuilder.addQueryParameter(it.key, it.value.toString())
}
}
}
val request = Request.Builder()
.url(httpBuilder.build())
.headers(requestHeaders)
.get()
.build()
return awaitResponse(request)
}
val body = if (MultipartBody.FORM.toString() == headers["content-type"]) {
val builder = MultipartBody.Builder().setType(MultipartBody.FORM)
params.forEach {
when {
it.key == "file" -> {
val file = it.value as File
builder.addFormDataPart(it.key, file.name, file.asRequestBody())
}
it.value is List<*> -> {
val list = it.value as List<*>
for (index in list.indices) {
builder.addFormDataPart(
"${it.key}[]",
list[index].toString()
)
}
}
else -> {
builder.addFormDataPart(it.key, it.value.toString())
}
}
}
builder.build()
} else {
Gson().toJson(params)
.toRequestBody("application/json".toMediaType())
}
val request = Request.Builder()
.url(httpBuilder.build())
.headers(requestHeaders)
.method(method, body)
.build()
return awaitResponse(request)
}
@Throws(AppwriteException::class)
private suspend fun awaitResponse(request: Request) = suspendCancellableCoroutine<Response> {
http.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
if (it.isCancelled) {
return
}
it.cancel(e)
}
override fun onResponse(call: Call, response: Response) {
if (response.code >= 400) {
val bodyString = response.body
?.charStream()
?.buffered()
?.use(BufferedReader::readText)
val error = bodyString?.fromJson(Error::class.java)
it.cancel(AppwriteException(
error?.message,
error?.code,
bodyString
))
}
it.resume(response)
}
})
}
}

View file

@ -0,0 +1,14 @@
package io.appwrite.services
import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
class KeepAliveService: Service() {
companion object {
val binder = Binder()
}
override fun onBind(intent: Intent) = binder
}

View file

@ -0,0 +1,100 @@
package io.appwrite
import android.content.Intent
import android.net.Uri
import androidx.activity.ComponentActivity
import androidx.browser.customtabs.CustomTabsIntent
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import io.appwrite.services.KeepAliveService
import kotlinx.coroutines.delay
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.forEach
import kotlin.collections.mutableMapOf
import kotlin.collections.set
/**
* Used to authenticate with external OAuth2 providers. Launches browser windows and handles
* suspension until the user completes the process or otherwise returns to the app.
*/
internal class WebAuthComponent {
companion object : DefaultLifecycleObserver {
private var suspended = false
private val callbacks = mutableMapOf<String, (((Result<String>) -> Unit)?)>()
override fun onResume(owner: LifecycleOwner) {
suspended = false
}
/**
* Authenticate Session with OAuth2
*
* Launches a chrome custom tab from the given activity and directs to the given url,
* suspending until the user returns to the app, at which point the given [onComplete] callback
* will run, passing the callback url from the intent used to launch the [CallbackActivity],
* or an [IllegalStateException] in the case the user closed the window or returned to the
* app without passing through the [CallbackActivity].
*
*
* @param activity The activity to launch the browser from and observe the lifecycle of
* @param url The url to launch
* @param callbackUrlScheme The callback url scheme used to key the given callback
* @param onComplete The callback to run when a result (success or failure) is received
*/
suspend fun authenticate(
activity: ComponentActivity,
url: Uri,
callbackUrlScheme: String,
onComplete: ((Result<String>) -> Unit)?
) {
val intent = CustomTabsIntent.Builder().build()
val keepAliveIntent = Intent(activity, KeepAliveService::class.java)
callbacks[callbackUrlScheme] = onComplete
intent.intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
intent.intent.putExtra("android.support.customtabs.extra.KEEP_ALIVE", keepAliveIntent)
intent.launchUrl(activity, url)
activity.runOnUiThread {
activity.lifecycle.addObserver(this)
}
// Need to dirty poll block so execution doesn't continue at the callsite of this function
suspended = true
while (suspended) {
delay(200)
}
cleanUp()
}
/**
* Trigger a web auth callback
*
* Attempts to find a callback for the given [scheme] and if found, invokes it, passing the
* given [url]. Calling this method stops auth suspension, so any calls to [authenticate]
* will continue execution from their suspension points immediately after this method
* is called.
*
* @param scheme The scheme to match to a callback's key
* @param url The url received through intent data from the [CallbackActivity]
*/
fun onCallback(scheme: String, url: Uri) {
callbacks.remove(scheme)?.invoke(
Result.success(url.toString())
)
suspended = false
}
private fun cleanUp() {
callbacks.forEach { (_, danglingResultCallback) ->
danglingResultCallback?.invoke(
Result.failure(IllegalStateException("User cancelled login"))
)
}
callbacks.clear()
}
}
}

View file

@ -0,0 +1,9 @@
package io.appwrite.exceptions
import java.lang.Exception
class AppwriteException(
message: String? = null,
val code: Int? = null,
val response: String? = null
) : Exception(message)

View file

@ -0,0 +1,12 @@
package io.appwrite.extensions
import com.google.gson.Gson
object JsonExtensions {
fun Any.toJson(): String =
Gson().toJson(this)
fun <T> String.fromJson(clazz: Class<T>): T =
Gson().fromJson(this, clazz)
}

View file

@ -0,0 +1,6 @@
package io.appwrite.models
data class Error(
val message: String,
val code: Int
)

View file

@ -0,0 +1,626 @@
package io.appwrite.services
import android.net.Uri
import io.appwrite.Client
import io.appwrite.WebAuthComponent
import androidx.activity.ComponentActivity
import io.appwrite.exceptions.AppwriteException
import okhttp3.Cookie
import okhttp3.Response
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import java.io.File
class Account(private val client: Client) : BaseService(client) {
/**
* Get Account
*
* Get currently logged in user data as JSON object.
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun get(): Response {
val path = "/account"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("GET", path, headers, params)
}
/**
* Create Account
*
* Use this endpoint to allow a new user to register a new account in your
* project. After the user registration completes successfully, you can use
* the [/account/verfication](/docs/client/account#accountCreateVerification)
* route to start verifying the user email address. To allow the new user to
* login to their new account, you need to create a new [account
* session](/docs/client/account#accountCreateSession).
*
* @param email
* @param password
* @param name
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun create(
email: String,
password: String,
name: String? = null
): Response {
val path = "/account"
val params = mapOf<String, Any?>(
"email" to email,
"password" to password,
"name" to name
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("POST", path, headers, params)
}
/**
* Delete Account
*
* Delete a currently logged in user account. Behind the scene, the user
* record is not deleted but permanently blocked from any access. This is done
* to avoid deleted accounts being overtaken by new users with the same email
* address. Any user-related resources like documents or storage files should
* be deleted separately.
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun delete(): Response {
val path = "/account"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("DELETE", path, headers, params)
}
/**
* Update Account Email
*
* Update currently logged in user account email address. After changing user
* address, user confirmation status is being reset and a new confirmation
* mail is sent. For security measures, user password is required to complete
* this request.
* This endpoint can also be used to convert an anonymous account to a normal
* one, by passing an email address and a new password.
*
* @param email
* @param password
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun updateEmail(
email: String,
password: String
): Response {
val path = "/account/email"
val params = mapOf<String, Any?>(
"email" to email,
"password" to password
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("PATCH", path, headers, params)
}
/**
* Create Account JWT
*
* Use this endpoint to create a JSON Web Token. You can use the resulting JWT
* to authenticate on behalf of the current user when working with the
* Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes
* from its creation and will be invalid if the user will logout.
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun createJWT(): Response {
val path = "/account/jwt"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("POST", path, headers, params)
}
/**
* Get Account Logs
*
* Get currently logged in user list of latest security activity logs. Each
* log returns user IP address, location and date and time of log.
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getLogs(): Response {
val path = "/account/logs"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("GET", path, headers, params)
}
/**
* Update Account Name
*
* Update currently logged in user account name.
*
* @param name
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun updateName(
name: String
): Response {
val path = "/account/name"
val params = mapOf<String, Any?>(
"name" to name
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("PATCH", path, headers, params)
}
/**
* Update Account Password
*
* Update currently logged in user password. For validation, user is required
* to pass in the new password, and the old password. For users created with
* OAuth and Team Invites, oldPassword is optional.
*
* @param password
* @param oldPassword
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun updatePassword(
password: String,
oldPassword: String? = null
): Response {
val path = "/account/password"
val params = mapOf<String, Any?>(
"password" to password,
"oldPassword" to oldPassword
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("PATCH", path, headers, params)
}
/**
* Get Account Preferences
*
* Get currently logged in user preferences as a key-value object.
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getPrefs(): Response {
val path = "/account/prefs"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("GET", path, headers, params)
}
/**
* Update Account Preferences
*
* Update currently logged in user account preferences. You can pass only the
* specific settings you wish to update.
*
* @param prefs
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun updatePrefs(
prefs: Any
): Response {
val path = "/account/prefs"
val params = mapOf<String, Any?>(
"prefs" to prefs
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("PATCH", path, headers, params)
}
/**
* Create Password Recovery
*
* Sends the user an email with a temporary secret key for password reset.
* When the user clicks the confirmation link he is redirected back to your
* app password reset URL with the secret key and email address values
* attached to the URL query string. Use the query string params to submit a
* request to the [PUT
* /account/recovery](/docs/client/account#accountUpdateRecovery) endpoint to
* complete the process. The verification link sent to the user's email
* address is valid for 1 hour.
*
* @param email
* @param url
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun createRecovery(
email: String,
url: String
): Response {
val path = "/account/recovery"
val params = mapOf<String, Any?>(
"email" to email,
"url" to url
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("POST", path, headers, params)
}
/**
* Complete Password Recovery
*
* Use this endpoint to complete the user account password reset. Both the
* **userId** and **secret** arguments will be passed as query parameters to
* the redirect URL you have provided when sending your request to the [POST
* /account/recovery](/docs/client/account#accountCreateRecovery) endpoint.
*
* Please note that in order to avoid a [Redirect
* Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
* the only valid redirect URLs are the ones from domains you have set when
* adding your platforms in the console interface.
*
* @param userId
* @param secret
* @param password
* @param passwordAgain
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun updateRecovery(
userId: String,
secret: String,
password: String,
passwordAgain: String
): Response {
val path = "/account/recovery"
val params = mapOf<String, Any?>(
"userId" to userId,
"secret" to secret,
"password" to password,
"passwordAgain" to passwordAgain
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("PUT", path, headers, params)
}
/**
* Get Account Sessions
*
* Get currently logged in user list of active sessions across different
* devices.
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getSessions(): Response {
val path = "/account/sessions"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("GET", path, headers, params)
}
/**
* Create Account Session
*
* Allow the user to login into their account by providing a valid email and
* password combination. This route will create a new session for the user.
*
* @param email
* @param password
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun createSession(
email: String,
password: String
): Response {
val path = "/account/sessions"
val params = mapOf<String, Any?>(
"email" to email,
"password" to password
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("POST", path, headers, params)
}
/**
* Delete All Account Sessions
*
* Delete all sessions from the user account and remove any sessions cookies
* from the end client.
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun deleteSessions(): Response {
val path = "/account/sessions"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("DELETE", path, headers, params)
}
/**
* Create Anonymous Session
*
* Use this endpoint to allow a new user to register an anonymous account in
* your project. This route will also create a new session for the user. To
* allow the new user to convert an anonymous account to a normal account
* account, you need to update its [email and
* password](/docs/client/account#accountUpdateEmail).
*
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun createAnonymousSession(): Response {
val path = "/account/sessions/anonymous"
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("POST", path, headers, params)
}
/**
* Create Account Session with OAuth2
*
* Allow the user to login to their account using the OAuth2 provider of their
* choice. Each OAuth2 provider should be enabled from the Appwrite console
* first. Use the success and failure arguments to provide a redirect URL's
* back to your app when login is completed.
*
* @param provider
* @param success
* @param failure
* @param scopes
*
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun createOAuth2Session(
activity: ComponentActivity,
provider: String,
success: String? = null,
failure: String? = null,
scopes: List<Any>? = null
) {
val path = "/account/sessions/oauth2/{provider}".replace("{provider}", provider)
val params = mapOf<String, Any?>(
"success" to success,
"failure" to failure,
"scopes" to scopes,
"project" to client.config["project"]
)
val query = mutableListOf<String>()
params.forEach {
when (it.value) {
null -> {
return@forEach
}
is List<*> -> {
query.add("${it.key}[]=${it.value.toString()}")
}
else -> {
query.add("${it.key}=${it.value.toString()}")
}
}
}
val url = Uri.parse("${client.endPoint}${path}?${query.joinToString("&")}")
val callbackUrlScheme = "appwrite-callback-${client.config["project"]}"
WebAuthComponent.authenticate(activity, url, callbackUrlScheme) {
if (it.isFailure) {
throw it.exceptionOrNull()!!
}
val resultUrl = it.getOrNull()!!
val uri = Uri.parse(resultUrl)
val key = uri.getQueryParameter("key")
val secret = uri.getQueryParameter("secret")
if (key == null || secret == null) {
throw AppwriteException("Authentication cookie missing!")
}
val cookie = Cookie.Builder()
.name(key)
.value(secret)
.domain(Uri.parse(client.endPoint).host!!)
.httpOnly()
.build()
client.cookieJar.saveFromResponse(
client.endPoint.toHttpUrl(),
listOf(cookie)
)
}
}
/**
* Delete Account Session
*
* Use this endpoint to log out the currently logged in user from all their
* account sessions across all of their different devices. When using the
* option id argument, only the session unique ID provider will be deleted.
*
* @param sessionId
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun deleteSession(
sessionId: String
): Response {
val path = "/account/sessions/{sessionId}".replace("{sessionId}", sessionId)
val params = mapOf<String, Any?>(
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("DELETE", path, headers, params)
}
/**
* Create Email Verification
*
* Use this endpoint to send a verification message to your user email address
* to confirm they are the valid owners of that address. Both the **userId**
* and **secret** arguments will be passed as query parameters to the URL you
* have provided to be attached to the verification email. The provided URL
* should redirect the user back to your app and allow you to complete the
* verification process by verifying both the **userId** and **secret**
* parameters. Learn more about how to [complete the verification
* process](/docs/client/account#accountUpdateVerification). The verification
* link sent to the user's email address is valid for 7 days.
*
* Please note that in order to avoid a [Redirect
* Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md),
* the only valid redirect URLs are the ones from domains you have set when
* adding your platforms in the console interface.
*
*
* @param url
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun createVerification(
url: String
): Response {
val path = "/account/verification"
val params = mapOf<String, Any?>(
"url" to url
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("POST", path, headers, params)
}
/**
* Complete Email Verification
*
* Use this endpoint to complete the user email verification process. Use both
* the **userId** and **secret** parameters that were attached to your app URL
* to verify the user email ownership. If confirmed this route will return a
* 200 status code.
*
* @param userId
* @param secret
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun updateVerification(
userId: String,
secret: String
): Response {
val path = "/account/verification"
val params = mapOf<String, Any?>(
"userId" to userId,
"secret" to secret
)
val headers = mapOf(
"content-type" to "application/json"
)
return client.call("PUT", path, headers, params)
}
}

View file

@ -0,0 +1,241 @@
package io.appwrite.services
import android.net.Uri
import io.appwrite.Client
import io.appwrite.exceptions.AppwriteException
import okhttp3.Cookie
import okhttp3.Response
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import java.io.File
class Avatars(private val client: Client) : BaseService(client) {
/**
* Get Browser Icon
*
* You can use this endpoint to show different browser icons to your users.
* The code argument receives the browser code as it appears in your user
* /account/sessions endpoint. Use width, height and quality arguments to
* change the output settings.
*
* @param code
* @param width
* @param height
* @param quality
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getBrowser(
code: String,
width: Int? = null,
height: Int? = null,
quality: Int? = null
): Response {
val path = "/avatars/browsers/{code}".replace("{code}", code)
val params = mapOf<String, Any?>(
"width" to width,
"height" to height,
"quality" to quality,
"project" to client.config["project"]
)
return client.call("GET", path, params = params)
}
/**
* Get Credit Card Icon
*
* The credit card endpoint will return you the icon of the credit card
* provider you need. Use width, height and quality arguments to change the
* output settings.
*
* @param code
* @param width
* @param height
* @param quality
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getCreditCard(
code: String,
width: Int? = null,
height: Int? = null,
quality: Int? = null
): Response {
val path = "/avatars/credit-cards/{code}".replace("{code}", code)
val params = mapOf<String, Any?>(
"width" to width,
"height" to height,
"quality" to quality,
"project" to client.config["project"]
)
return client.call("GET", path, params = params)
}
/**
* Get Favicon
*
* Use this endpoint to fetch the favorite icon (AKA favicon) of any remote
* website URL.
*
*
* @param url
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getFavicon(
url: String
): Response {
val path = "/avatars/favicon"
val params = mapOf<String, Any?>(
"url" to url,
"project" to client.config["project"]
)
return client.call("GET", path, params = params)
}
/**
* Get Country Flag
*
* You can use this endpoint to show different country flags icons to your
* users. The code argument receives the 2 letter country code. Use width,
* height and quality arguments to change the output settings.
*
* @param code
* @param width
* @param height
* @param quality
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getFlag(
code: String,
width: Int? = null,
height: Int? = null,
quality: Int? = null
): Response {
val path = "/avatars/flags/{code}".replace("{code}", code)
val params = mapOf<String, Any?>(
"width" to width,
"height" to height,
"quality" to quality,
"project" to client.config["project"]
)
return client.call("GET", path, params = params)
}
/**
* Get Image from URL
*
* Use this endpoint to fetch a remote image URL and crop it to any image size
* you want. This endpoint is very useful if you need to crop and display
* remote images in your app or in case you want to make sure a 3rd party
* image is properly served using a TLS protocol.
*
* @param url
* @param width
* @param height
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getImage(
url: String,
width: Int? = null,
height: Int? = null
): Response {
val path = "/avatars/image"
val params = mapOf<String, Any?>(
"url" to url,
"width" to width,
"height" to height,
"project" to client.config["project"]
)
return client.call("GET", path, params = params)
}
/**
* Get User Initials
*
* Use this endpoint to show your user initials avatar icon on your website or
* app. By default, this route will try to print your logged-in user name or
* email initials. You can also overwrite the user name if you pass the 'name'
* parameter. If no name is given and no user is logged, an empty avatar will
* be returned.
*
* You can use the color and background params to change the avatar colors. By
* default, a random theme will be selected. The random theme will persist for
* the user's initials when reloading the same theme will always return for
* the same initials.
*
* @param name
* @param width
* @param height
* @param color
* @param background
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getInitials(
name: String? = null,
width: Int? = null,
height: Int? = null,
color: String? = null,
background: String? = null
): Response {
val path = "/avatars/initials"
val params = mapOf<String, Any?>(
"name" to name,
"width" to width,
"height" to height,
"color" to color,
"background" to background,
"project" to client.config["project"]
)
return client.call("GET", path, params = params)
}
/**
* Get QR Code
*
* Converts a given plain text to a QR code image. You can use the query
* parameters to change the size and style of the resulting image.
*
* @param text
* @param size
* @param margin
* @param download
* @return [Response]
*/
@JvmOverloads
@Throws(AppwriteException::class)
suspend fun getQR(
text: String,
size: Int? = null,
margin: Int? = null,
download: Boolean? = null
): Response {
val path = "/avatars/qr"
val params = mapOf<String, Any?>(
"text" to text,
"size" to size,
"margin" to margin,
"download" to download,
"project" to client.config["project"]
)
return client.call("GET", path, params = params)
}
}

Some files were not shown because too many files have changed in this diff Show more