Merge pull request #17 from archem-team/feat/messages-deeplink
Feat/messages deeplink
This commit is contained in:
commit
8e19376e29
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
run: |
|
||||
gh api graphql -f query='
|
||||
query {
|
||||
organization(login: "revoltchat"){
|
||||
organization(login: "peptidechat"){
|
||||
projectV2(number: 3) {
|
||||
id
|
||||
fields(first:20) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
run: |
|
||||
gh api graphql -f query='
|
||||
query {
|
||||
organization(login: "revoltchat"){
|
||||
organization(login: "peptidechat"){
|
||||
projectV2(number: 5) {
|
||||
id
|
||||
fields(first:20) {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@
|
|||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
revoltbuild.properties
|
||||
sentry.properties
|
||||
peptidebuild.properties
|
||||
/.kotlin/sessions
|
||||
app/src/main/assets/embedded
|
||||
pep-api-postman.json
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
PEP
|
||||
PepChat
|
||||
24
README.md
24
README.md
|
|
@ -1,14 +1,14 @@
|
|||
# Revolt on Android
|
||||
# Peptide on Android
|
||||
|
||||
## Description
|
||||
|
||||
This is the official Android app for the [Revolt](https://revolt.chat) chat platform.
|
||||
The codebase includes the app itself, as well as an internal library for interacting with the Revolt
|
||||
This is the official Android app for the [Peptide](https://peptide.chat) chat platform.
|
||||
The codebase includes the app itself, as well as an internal library for interacting with the Peptide
|
||||
API.
|
||||
|
||||
| Module | Package | Description |
|
||||
|--------|---------------|----------------------|
|
||||
| `:app` | `chat.revolt` | The main app module. |
|
||||
| `:app` | `chat.peptide` | The main app module. |
|
||||
|
||||
The API library is part of the `app` module, and is not intended to be used as a standalone library,
|
||||
as it makes liberal use of Android-specific APIs for reactivity.
|
||||
|
|
@ -29,18 +29,18 @@ of the art for Android UI development.
|
|||
|
||||
## Resources
|
||||
|
||||
### Revolt on Android
|
||||
### Peptide on Android
|
||||
|
||||
- [Revolt on Android Technical Documentation](https://revoltchat.github.io/android/)
|
||||
- [Android-specific Contribution Guide](https://revoltchat.github.io/android/contributing/guidelines/)
|
||||
- [Peptide on Android Technical Documentation](https://peptidechat.github.io/android/)
|
||||
- [Android-specific Contribution Guide](https://peptidechat.github.io/android/contributing/guidelines/)
|
||||
—**read carefully before contributing!**
|
||||
|
||||
### Revolt
|
||||
### Peptide
|
||||
|
||||
- [Revolt Project Board](https://github.com/revoltchat/revolt/discussions) (Submit feature requests
|
||||
- [Peptide Project Board](https://github.com/peptidechat/peptide/discussions) (Submit feature requests
|
||||
here)
|
||||
- [Revolt Testers Server](https://app.revolt.chat/invite/Testers)
|
||||
- [General Revolt Contribution Guide](https://developers.revolt.chat/contributing)
|
||||
- [Peptide Testers Server](https://app.peptide.chat/invite/Testers)
|
||||
- [General Peptide Contribution Guide](https://developers.peptide.chat/contributing)
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
|
@ -48,4 +48,4 @@ Open the project in Android Studio. You can then run the app on an emulator or a
|
|||
running the `app` module.
|
||||
|
||||
In-depth setup instructions can be found
|
||||
at [Setting up your Development Environment](https://revoltchat.github.io/android/contributing/setup/)
|
||||
at [Setting up your Development Environment](https://peptidechat.github.io/android/contributing/setup/)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import com.mikepenz.aboutlibraries.plugin.StrictMode
|
||||
import io.sentry.android.gradle.instrumentation.logcat.LogcatLevel
|
||||
import java.io.FileInputStream
|
||||
import java.util.Properties
|
||||
|
||||
|
|
@ -12,7 +11,6 @@ plugins {
|
|||
id("com.google.dagger.hilt.android")
|
||||
id("com.google.devtools.ksp")
|
||||
id("org.jmailen.kotlinter")
|
||||
id("io.sentry.android.gradle") version "4.12.0"
|
||||
id("app.cash.sqldelight") version "2.0.1"
|
||||
id("kotlin-kapt")
|
||||
id("kotlin-parcelize")
|
||||
|
|
@ -21,7 +19,6 @@ plugins {
|
|||
|
||||
val composeBomVersion = "2025.03.00"
|
||||
val accompanistVersion = "0.34.0"
|
||||
val okhttpVersion = "4.12.0"
|
||||
val navVersion = "2.9.0"
|
||||
val hiltVersion = "2.52"
|
||||
val glideVersion = "4.16.0"
|
||||
|
|
@ -30,11 +27,6 @@ val media3Version = "1.7.1"
|
|||
val material3Version = "1.4.0-alpha15"
|
||||
val androidXTestVersion = "1.6.1"
|
||||
|
||||
object LivekitVersion {
|
||||
val core = "2.16.0"
|
||||
val componentsCompose = "1.3.1"
|
||||
}
|
||||
|
||||
fun property(fileName: String, propertyName: String, fallbackEnv: String? = null): String? {
|
||||
val propsFile = rootProject.file(fileName)
|
||||
if (propsFile.exists()) {
|
||||
|
|
@ -68,16 +60,16 @@ fun property(fileName: String, propertyName: String, fallbackEnv: String? = null
|
|||
}
|
||||
}
|
||||
|
||||
// Calls property but with revoltbuild.properties as the first argument
|
||||
// Calls property but with peptidebuild.properties as the first argument
|
||||
fun buildproperty(propertyName: String, fallbackEnv: String? = null): String? {
|
||||
return property("revoltbuild.properties", propertyName, fallbackEnv)
|
||||
return property("peptidebuild.properties", propertyName, fallbackEnv)
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = 35
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "chat.revolt"
|
||||
applicationId = "chat.peptide"
|
||||
minSdk = 24
|
||||
targetSdk = 35
|
||||
versionCode = Integer.parseInt("001_003_106".replace("_", ""), 10)
|
||||
|
|
@ -103,11 +95,6 @@ android {
|
|||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
buildConfigField(
|
||||
"String",
|
||||
"SENTRY_DSN",
|
||||
"\"${buildproperty("sentry.dsn", "RVX_SENTRY_DSN")}\""
|
||||
)
|
||||
buildConfigField(
|
||||
"String",
|
||||
"FLAVOUR_ID",
|
||||
|
|
@ -126,11 +113,11 @@ android {
|
|||
buildproperty("build.debug.app_name", "RVX_DEBUG_APP_NAME")!!
|
||||
)
|
||||
|
||||
buildConfigField(
|
||||
"String",
|
||||
"SENTRY_DSN",
|
||||
"\"${buildproperty("sentry.dsn", "RVX_SENTRY_DSN")}\""
|
||||
)
|
||||
// buildConfigField(
|
||||
// "String",
|
||||
// "SENTRY_DSN",
|
||||
// "\"${buildproperty("sentry.dsn", "RVX_SENTRY_DSN")}\""
|
||||
// )
|
||||
buildConfigField(
|
||||
"String",
|
||||
"FLAVOUR_ID",
|
||||
|
|
@ -159,7 +146,7 @@ android {
|
|||
androidResources {
|
||||
generateLocaleConfig = true
|
||||
}
|
||||
namespace = "chat.revolt"
|
||||
namespace = "chat.peptide"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path(file("src/main/cpp/CMakeLists.txt"))
|
||||
|
|
@ -169,22 +156,24 @@ android {
|
|||
lint {
|
||||
abortOnError = false
|
||||
disable += "MissingTranslation"
|
||||
disable += "NullSafeMutableLiveData"
|
||||
checkReleaseBuilds = false
|
||||
}
|
||||
}
|
||||
|
||||
sentry {
|
||||
autoUploadProguardMapping =
|
||||
buildproperty("sentry.upload_mappings", "RVX_SENTRY_UPLOAD_MAPPINGS") == "true"
|
||||
|
||||
tracingInstrumentation {
|
||||
enabled = true
|
||||
|
||||
logcat {
|
||||
enabled = true
|
||||
minLevel = LogcatLevel.WARNING
|
||||
}
|
||||
}
|
||||
}
|
||||
//sentry {
|
||||
// autoUploadProguardMapping =
|
||||
// buildproperty("sentry.upload_mappings", "RVX_SENTRY_UPLOAD_MAPPINGS") == "true"
|
||||
//
|
||||
// tracingInstrumentation {
|
||||
// enabled = true
|
||||
//
|
||||
// logcat {
|
||||
// enabled = true
|
||||
// minLevel = LogcatLevel.WARNING
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
dependencies {
|
||||
// Android/Kotlin Core
|
||||
|
|
@ -196,6 +185,10 @@ dependencies {
|
|||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-cbor:1.6.1")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||
implementation("androidx.profileinstaller:profileinstaller:1.4.1")
|
||||
implementation("androidx.camera:camera-core:1.4.2")
|
||||
implementation("androidx.camera:camera-lifecycle:1.4.2")
|
||||
implementation("androidx.camera:camera-camera2:1.4.2")
|
||||
implementation("androidx.camera:camera-view:1.4.2")
|
||||
|
||||
// Compose BOM
|
||||
val composeBom = platform("androidx.compose:compose-bom:$composeBomVersion")
|
||||
|
|
@ -247,8 +240,8 @@ dependencies {
|
|||
implementation("com.mikepenz:aboutlibraries-core:11.3.0-rc02")
|
||||
|
||||
// Sentry - crash reporting
|
||||
implementation("io.sentry:sentry-android:8.13.2")
|
||||
implementation("io.sentry:sentry-compose-android:8.13.2")
|
||||
// implementation("io.sentry:sentry-android:8.19.1")
|
||||
// implementation("io.sentry:sentry-compose-android:8.19.1")
|
||||
|
||||
// Other AndroidX libraries
|
||||
implementation("androidx.documentfile:documentfile:1.1.0")
|
||||
|
|
@ -343,7 +336,7 @@ aboutLibraries {
|
|||
sqldelight {
|
||||
databases {
|
||||
create("Database") {
|
||||
packageName.set("chat.revolt.persistence")
|
||||
packageName.set("chat.peptide.persistence")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,4 +109,4 @@
|
|||
public <fields>;
|
||||
}
|
||||
|
||||
-keep class chat.revolt.ndk.AstNode { *; }
|
||||
-keep class chat.peptide.ndk.AstNode { *; }
|
||||
|
|
@ -19,6 +19,9 @@
|
|||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
-->
|
||||
|
||||
<!-- Camera permission required for CameraX usage -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
|
|
@ -31,8 +34,8 @@
|
|||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:name=".RevoltApplication"
|
||||
android:theme="@style/Theme.Revolt"
|
||||
android:name=".PeptideApplication"
|
||||
android:theme="@style/Theme.Peptide"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
tools:targetApi="tiramisu">
|
||||
<provider
|
||||
|
|
@ -45,9 +48,9 @@
|
|||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<meta-data
|
||||
android:name="io.sentry.auto-init"
|
||||
android:value="false" />
|
||||
<!-- <meta-data-->
|
||||
<!-- android:name="io.sentry.auto-init"-->
|
||||
<!-- android:value="false" />-->
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||
|
|
@ -69,7 +72,7 @@
|
|||
android:exported="true"
|
||||
android:configChanges="orientation|screenSize|colorMode"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:theme="@style/Theme.Revolt">
|
||||
android:theme="@style/Theme.Peptide">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
|
@ -79,7 +82,7 @@
|
|||
|
||||
<activity
|
||||
android:name=".activities.InviteActivity"
|
||||
android:theme="@style/Theme.Revolt"
|
||||
android:theme="@style/Theme.Peptide"
|
||||
android:exported="true">
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
|
@ -90,7 +93,7 @@
|
|||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
|
||||
<data android:host="app.revolt.chat" />
|
||||
<data android:host="app.peptide.chat" />
|
||||
|
||||
<data android:pathPrefix="/invite/" />
|
||||
</intent-filter>
|
||||
|
|
@ -115,7 +118,7 @@
|
|||
|
||||
<activity
|
||||
android:name=".activities.ShareTargetActivity"
|
||||
android:theme="@style/Theme.Revolt"
|
||||
android:theme="@style/Theme.Peptide"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
|
@ -131,12 +134,12 @@
|
|||
|
||||
<activity
|
||||
android:name=".activities.media.ImageViewActivity"
|
||||
android:theme="@style/Theme.Revolt" />
|
||||
android:theme="@style/Theme.Peptide" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.media.VideoViewActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:theme="@style/Theme.Revolt" />
|
||||
android:theme="@style/Theme.Peptide" />
|
||||
|
||||
<!-- Backport photo picker via Google Play Services -->
|
||||
<service
|
||||
|
|
@ -161,6 +164,34 @@
|
|||
android:value="true" />
|
||||
</service>
|
||||
|
||||
<!-- DeepLink Activity for handling App Links -->
|
||||
<activity
|
||||
android:name=".activities.DeepLinkActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.Peptide">
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:scheme="http" />
|
||||
<data android:host="peptide.chat" />
|
||||
<data android:host="app.peptide.chat" />
|
||||
|
||||
<!-- Channel deep links -->
|
||||
<data android:pathPrefix="/channels/" />
|
||||
<!-- Server deep links -->
|
||||
<data android:pathPrefix="/servers/" />
|
||||
<data android:pathPrefix="/server/" />
|
||||
<!-- User deep links -->
|
||||
<data android:pathPrefix="/users/" />
|
||||
<!-- Message deep links -->
|
||||
<data android:pathPrefix="/messages/" />
|
||||
<!-- Server channel message deep links -->
|
||||
<data android:pathPattern="/server/.*/channel/.*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
# Android App Links Setup Instructions
|
||||
|
||||
This document provides instructions for setting up Android App Links for the Peptide app.
|
||||
|
||||
## What are Android App Links?
|
||||
|
||||
Android App Links are HTTP URLs that bring users directly to specific content in your Android app. When a user clicks an App Link, the app opens immediately if it's installed, without showing the app chooser dialog.
|
||||
|
||||
## Requirements
|
||||
|
||||
1. Your app must have an intent filter that handles the specific URLs
|
||||
2. Your website must have a Digital Asset Links JSON file that verifies the association with your app
|
||||
|
||||
## Steps to Complete the Setup
|
||||
|
||||
### 1. Get your app's signing certificate fingerprint
|
||||
|
||||
Run the following command to get your app's signing certificate fingerprint:
|
||||
|
||||
```bash
|
||||
keytool -list -v -keystore your_keystore.jks -alias your_alias
|
||||
```
|
||||
|
||||
Look for the SHA-256 fingerprint in the output. Remove all colons (:) from the fingerprint.
|
||||
|
||||
### 2. Update the assetlinks.json file
|
||||
|
||||
Open the `assetlinks.json` file in this directory and replace the placeholder with your actual SHA-256 fingerprint:
|
||||
|
||||
```json
|
||||
[{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "chat.peptide",
|
||||
"sha256_cert_fingerprints": [
|
||||
"YOUR_SHA256_FINGERPRINT_HERE"
|
||||
]
|
||||
}
|
||||
}]
|
||||
```
|
||||
|
||||
### 3. Host the assetlinks.json file on your server
|
||||
|
||||
Upload the `assetlinks.json` file to the following location on your server:
|
||||
|
||||
```
|
||||
https://peptide.chat/.well-known/assetlinks.json
|
||||
https://app.peptide.chat/.well-known/assetlinks.json
|
||||
```
|
||||
|
||||
Make sure the file is accessible via HTTPS and returns with Content-Type: application/json.
|
||||
|
||||
### 4. Test your App Links
|
||||
|
||||
Use the Android Debug Bridge (ADB) to test your App Links:
|
||||
|
||||
```bash
|
||||
adb shell am start -a android.intent.action.VIEW -d "https://peptide.chat/channels/CHANNEL_ID" chat.peptide
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If your App Links aren't working:
|
||||
|
||||
1. Verify that the assetlinks.json file is accessible via HTTPS
|
||||
2. Check that the SHA-256 fingerprint in the assetlinks.json file matches your app's signing certificate
|
||||
3. Make sure your app is using the correct signing certificate
|
||||
4. Use the App Links Assistant in Android Studio to verify your App Links setup
|
||||
|
||||
For more information, see the [Android App Links documentation](https://developer.android.com/training/app-links).
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
[{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "chat.peptide",
|
||||
"sha256_cert_fingerprints": [
|
||||
"PUT_YOUR_APP_SIGNING_CERTIFICATE_SHA256_FINGERPRINT_HERE"
|
||||
]
|
||||
}
|
||||
}]
|
||||
|
|
@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.22.1)
|
|||
# Since this is the top level CMakeLists.txt, the project name is also accessible
|
||||
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
|
||||
# build script scope).
|
||||
project("revolt")
|
||||
project("peptide")
|
||||
|
||||
# Compile cmark in external/cmark
|
||||
add_subdirectory(external/cmark)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace Stendal {
|
|||
constructArrayListMethod = env->GetMethodID(localArrayListClass, "<init>", "(I)V");
|
||||
addArrayListMethod = env->GetMethodID(localArrayListClass, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
jclass localAstNodeClass = env->FindClass("chat/revolt/ndk/AstNode");
|
||||
jclass localAstNodeClass = env->FindClass("chat/peptide/ndk/AstNode");
|
||||
astNodeClass = (jclass) env->NewGlobalRef(localAstNodeClass);
|
||||
astNodeConstructor = env->GetMethodID(localAstNodeClass, "<init>",
|
||||
STENDAL_ASTNODE_CONSTRUCTOR_SIGNATURE);
|
||||
|
|
@ -141,12 +141,12 @@ namespace Stendal {
|
|||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_chat_revolt_ndk_Stendal_init(JNIEnv *env, [[maybe_unused]] jobject thiz) {
|
||||
Java_chat_peptide_ndk_Stendal_init(JNIEnv *env, [[maybe_unused]] jobject thiz) {
|
||||
Stendal::init(env);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
Java_chat_revolt_ndk_Stendal_render(JNIEnv *env, [[maybe_unused]] jobject thiz, jstring input) {
|
||||
Java_chat_peptide_ndk_Stendal_render(JNIEnv *env, [[maybe_unused]] jobject thiz, jstring input) {
|
||||
const char *inputStr = env->GetStringUTFChars(input, nullptr);
|
||||
cmark_node *doc = cmark_parse_document(inputStr, strlen(inputStr),
|
||||
CMARK_OPT_DEFAULT | CMARK_OPT_HARDBREAKS |
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
package chat.revolt
|
||||
package chat.peptide
|
||||
|
||||
import android.app.Application
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.persistence.KVStorage
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import logcat.AndroidLogcatLogger
|
||||
import logcat.LogPriority
|
||||
|
||||
@HiltAndroidApp
|
||||
class RevoltApplication : Application() {
|
||||
class PeptideApplication : Application() {
|
||||
companion object {
|
||||
lateinit var instance: RevoltApplication
|
||||
lateinit var instance: PeptideApplication
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
AndroidLogcatLogger.installOnDebuggableApp(this, minPriority = LogPriority.VERBOSE)
|
||||
RevoltHttp // Trigger initialization
|
||||
PeptideHttp // Trigger initialization
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
@ -30,6 +30,6 @@ class RevoltApplication : Application() {
|
|||
* Extension function to get KVStorage instance.
|
||||
* @return KVStorage instance
|
||||
*/
|
||||
fun RevoltApplication.getKVStorage(): KVStorage {
|
||||
fun PeptideApplication.getKVStorage(): KVStorage {
|
||||
return KVStorage(this)
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
package chat.peptide.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import chat.peptide.persistence.KVStorage
|
||||
import chat.peptide.utils.DeepLinkUtils
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DeepLinkActivity : AppCompatActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var kvStorage: KVStorage
|
||||
|
||||
companion object {
|
||||
private const val TAG = "DeepLinkActivity"
|
||||
|
||||
// Constants for deep link paths
|
||||
const val PATH_CHANNEL = "channel"
|
||||
const val PATH_SERVER = "server"
|
||||
const val PATH_USER = "user"
|
||||
const val PATH_MESSAGE = "message"
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Handle the incoming intent
|
||||
handleIntent(intent)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
|
||||
// Handle the new intent
|
||||
handleIntent(intent)
|
||||
}
|
||||
|
||||
private fun handleIntent(intent: Intent) {
|
||||
val appLinkAction = intent.action
|
||||
val appLinkData: Uri? = intent.data
|
||||
|
||||
if (Intent.ACTION_VIEW == appLinkAction && appLinkData != null) {
|
||||
Log.d(TAG, "Deep link received: $appLinkData")
|
||||
|
||||
// Check if this is a valid Peptide deep link
|
||||
if (!DeepLinkUtils.isPeptideDeepLink(appLinkData)) {
|
||||
Log.d(TAG, "Not a valid Peptide deep link: $appLinkData")
|
||||
startMainActivity()
|
||||
return
|
||||
}
|
||||
|
||||
// Check if user is logged in and handle deep link in a coroutine
|
||||
lifecycleScope.launch {
|
||||
val token = kvStorage.get("sessionToken")
|
||||
if (token == null) {
|
||||
// User is not logged in, redirect to login screen
|
||||
Log.d(TAG, "User not logged in, redirecting to login screen")
|
||||
startMainActivity("choose-platform")
|
||||
return@launch
|
||||
}
|
||||
|
||||
// First, check for server/channel/message format
|
||||
val serverChannelMessage = DeepLinkUtils.extractServerChannelMessage(appLinkData)
|
||||
if (serverChannelMessage != null) {
|
||||
Log.d(TAG, "Detected server/channel/message format: ${serverChannelMessage.serverId}/${serverChannelMessage.channelId}/${serverChannelMessage.messageId}")
|
||||
|
||||
if (serverChannelMessage.messageId != null) {
|
||||
// Navigate to the specific message in the channel
|
||||
navigateToMessage(serverChannelMessage.messageId, serverChannelMessage.channelId)
|
||||
} else {
|
||||
// Navigate to the channel in the server
|
||||
navigateToChannel(serverChannelMessage.channelId)
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
|
||||
// Extract IDs from the URI using our utility class for other formats
|
||||
val channelId = DeepLinkUtils.extractChannelId(appLinkData)
|
||||
val serverId = DeepLinkUtils.extractServerId(appLinkData)
|
||||
val userId = DeepLinkUtils.extractUserId(appLinkData)
|
||||
val messageId = DeepLinkUtils.extractMessageId(appLinkData)
|
||||
|
||||
when {
|
||||
channelId != null -> {
|
||||
Log.d(TAG, "Navigating to channel: $channelId")
|
||||
navigateToChannel(channelId)
|
||||
}
|
||||
serverId != null -> {
|
||||
Log.d(TAG, "Navigating to server: $serverId")
|
||||
navigateToServer(serverId)
|
||||
}
|
||||
userId != null -> {
|
||||
Log.d(TAG, "Navigating to user: $userId")
|
||||
navigateToUser(userId)
|
||||
}
|
||||
messageId != null -> {
|
||||
Log.d(TAG, "Navigating to message: $messageId")
|
||||
val channelParam = appLinkData.getQueryParameter("channel")
|
||||
navigateToMessage(messageId, channelParam)
|
||||
}
|
||||
else -> {
|
||||
// Default case, just open the main activity
|
||||
Log.d(TAG, "No specific path, opening main activity")
|
||||
startMainActivity()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Not a deep link, just open the main activity
|
||||
Log.d(TAG, "Not a deep link, opening main activity")
|
||||
startMainActivity()
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToChannel(channelId: String) {
|
||||
Log.d(TAG, "Navigating to channel: $channelId")
|
||||
|
||||
// Use our utility class to create the intent
|
||||
val intent = DeepLinkUtils.createChannelIntent(this, channelId)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun navigateToServer(serverId: String) {
|
||||
Log.d(TAG, "Navigating to server: $serverId")
|
||||
|
||||
// Use our utility class to create the intent
|
||||
val intent = DeepLinkUtils.createServerIntent(this, serverId)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun navigateToUser(userId: String) {
|
||||
Log.d(TAG, "Navigating to user: $userId")
|
||||
|
||||
// Use our utility class to create the intent
|
||||
val intent = DeepLinkUtils.createUserIntent(this, userId)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun navigateToMessage(messageId: String, channelId: String?) {
|
||||
Log.d(TAG, "Navigating to message: $messageId in channel: $channelId")
|
||||
|
||||
// Use our utility class to create the intent
|
||||
val intent = DeepLinkUtils.createMessageIntent(this, messageId, channelId)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun startMainActivity(destination: String? = null) {
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
if (destination != null) {
|
||||
intent.putExtra("next_destination", destination)
|
||||
}
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.activities
|
||||
package chat.peptide.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
|
|
@ -17,13 +17,11 @@ import androidx.compose.foundation.layout.size
|
|||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
|
|
@ -46,19 +44,21 @@ import androidx.core.view.WindowCompat
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.routes.invites.fetchInviteByCode
|
||||
import chat.revolt.api.routes.invites.joinInviteByCode
|
||||
import chat.revolt.api.schemas.Invite
|
||||
import chat.revolt.api.schemas.InviteJoined
|
||||
import chat.revolt.api.schemas.RsResult
|
||||
import chat.revolt.api.settings.LoadedSettings
|
||||
import chat.revolt.api.settings.SyncedSettings
|
||||
import chat.revolt.composables.generic.IconPlaceholder
|
||||
import chat.revolt.composables.generic.RemoteImage
|
||||
import chat.revolt.ui.theme.RevoltTheme
|
||||
import chat.peptide.R
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.routes.invites.fetchInviteByCode
|
||||
import chat.peptide.api.routes.invites.joinInviteByCode
|
||||
import chat.peptide.api.schemas.Invite
|
||||
import chat.peptide.api.schemas.InviteJoined
|
||||
import chat.peptide.api.schemas.RsResult
|
||||
import chat.peptide.api.settings.LoadedSettings
|
||||
import chat.peptide.api.settings.SyncedSettings
|
||||
import chat.peptide.composables.generic.IconPlaceholder
|
||||
import chat.peptide.composables.generic.PepTextButton
|
||||
import chat.peptide.composables.generic.RemoteImage
|
||||
import chat.peptide.composables.generic.SquareButton
|
||||
import chat.peptide.ui.theme.PeptideTheme
|
||||
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
|
||||
import com.bumptech.glide.integration.compose.GlideImage
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -90,19 +90,19 @@ class InviteViewModel : ViewModel() {
|
|||
_loadingFinished = loadingFinished
|
||||
}
|
||||
|
||||
private var _inviteResult by mutableStateOf<RsResult<Invite, RevoltError>?>(null)
|
||||
val inviteResult: RsResult<Invite, RevoltError>?
|
||||
private var _inviteResult by mutableStateOf<RsResult<Invite, PeptideError>?>(null)
|
||||
val inviteResult: RsResult<Invite, PeptideError>?
|
||||
get() = _inviteResult
|
||||
|
||||
fun setInviteResult(inviteResult: RsResult<Invite, RevoltError>?) {
|
||||
fun setInviteResult(inviteResult: RsResult<Invite, PeptideError>?) {
|
||||
_inviteResult = inviteResult
|
||||
}
|
||||
|
||||
private var _joinResult by mutableStateOf<RsResult<InviteJoined, RevoltError>?>(null)
|
||||
val joinResult: RsResult<InviteJoined, RevoltError>?
|
||||
private var _joinResult by mutableStateOf<RsResult<InviteJoined, PeptideError>?>(null)
|
||||
val joinResult: RsResult<InviteJoined, PeptideError>?
|
||||
get() = _joinResult
|
||||
|
||||
fun setJoinResult(joinResult: RsResult<InviteJoined, RevoltError>?) {
|
||||
fun setJoinResult(joinResult: RsResult<InviteJoined, PeptideError>?) {
|
||||
_joinResult = joinResult
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ fun InviteScreen(
|
|||
val inviteValid = if (viewModel.loadingFinished) (viewModel.inviteResult?.ok ?: false) else null
|
||||
val invite = viewModel.inviteResult?.value
|
||||
|
||||
RevoltTheme(
|
||||
PeptideTheme(
|
||||
requestedTheme = LoadedSettings.theme,
|
||||
colourOverrides = SyncedSettings.android.colourOverrides
|
||||
) {
|
||||
|
|
@ -180,7 +180,7 @@ fun InviteScreen(
|
|||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
GlideImage(
|
||||
model = "${RevoltAPI.getCurrentFilesUrl()}/banners/${invite?.serverBanner?.id}/${invite?.serverBanner?.filename}",
|
||||
model = "${PeptideAPI.getCurrentFilesUrl()}/banners/${invite?.serverBanner?.id}/${invite?.serverBanner?.filename}",
|
||||
contentScale = ContentScale.Crop,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
|
|
@ -205,7 +205,7 @@ fun InviteScreen(
|
|||
) {
|
||||
if (invite?.serverIcon != null) {
|
||||
RemoteImage(
|
||||
url = "${RevoltAPI.getCurrentFilesUrl()}/icons/${invite.serverIcon.id}/${invite.serverIcon.filename}",
|
||||
url = "${PeptideAPI.getCurrentFilesUrl()}/icons/${invite.serverIcon.id}/${invite.serverIcon.filename}",
|
||||
allowAnimation = false,
|
||||
description = viewModel.inviteResult?.value?.serverName
|
||||
?: stringResource(id = R.string.unknown),
|
||||
|
|
@ -245,7 +245,7 @@ fun InviteScreen(
|
|||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Row {
|
||||
Button(
|
||||
SquareButton(
|
||||
onClick = {
|
||||
viewModel.joinInvite(inviteCode)
|
||||
},
|
||||
|
|
@ -257,7 +257,7 @@ fun InviteScreen(
|
|||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
|
||||
TextButton(
|
||||
PepTextButton(
|
||||
onClick = onFinish,
|
||||
modifier = Modifier
|
||||
.testTag("decline_invite")
|
||||
|
|
@ -274,7 +274,7 @@ fun InviteScreen(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun InvalidInviteError(error: RevoltError? = null, onDismissRequest: () -> Unit) {
|
||||
fun InvalidInviteError(error: PeptideError? = null, onDismissRequest: () -> Unit) {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
icon = {
|
||||
|
|
@ -307,7 +307,7 @@ fun InvalidInviteError(error: RevoltError? = null, onDismissRequest: () -> Unit)
|
|||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
PepTextButton(
|
||||
onClick = {
|
||||
onDismissRequest()
|
||||
}
|
||||
|
|
@ -347,7 +347,7 @@ fun NoInviteSpecifiedError(onDismissRequest: () -> Unit) {
|
|||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
PepTextButton(
|
||||
onClick = {
|
||||
onDismissRequest()
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
package chat.revolt.activities
|
||||
package chat.peptide.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.os.Bundle
|
||||
|
|
@ -72,71 +73,73 @@ import androidx.lifecycle.viewModelScope
|
|||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import chat.revolt.BuildConfig
|
||||
import chat.revolt.R
|
||||
import chat.revolt.RevoltApplication
|
||||
import chat.revolt.api.ApplicationPlatform
|
||||
import chat.revolt.api.HitRateLimitException
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltAPI.setPlatform
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.UrlsStorageKeys
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.routes.microservices.geo.queryGeo
|
||||
import chat.revolt.api.routes.microservices.health.healthCheck
|
||||
import chat.revolt.api.routes.onboard.needsOnboarding
|
||||
import chat.revolt.api.schemas.HealthNotice
|
||||
import chat.revolt.api.settings.Experiments
|
||||
import chat.revolt.api.settings.GeoStateProvider
|
||||
import chat.revolt.api.settings.LoadedSettings
|
||||
import chat.revolt.api.settings.SyncedSettings
|
||||
import chat.revolt.composables.generic.HealthAlert
|
||||
import chat.revolt.composables.voice.VoicePermissionSwitch
|
||||
import chat.revolt.composables.voice.VoiceSheet
|
||||
import chat.revolt.material.EasingTokens
|
||||
import chat.revolt.ndk.NativeLibraries
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.revolt.screens.DefaultDestinationScreen
|
||||
import chat.revolt.screens.about.AboutScreen
|
||||
import chat.revolt.screens.about.AttributionScreen
|
||||
import chat.revolt.screens.chat.ChatRouterScreen
|
||||
import chat.revolt.screens.chat.views.channel.ChannelScreen
|
||||
import chat.revolt.screens.chooseplatform.ChoosePlatformScreen
|
||||
import chat.revolt.screens.create.CreateGroupScreen
|
||||
import chat.revolt.screens.labs.LabsRootScreen
|
||||
import chat.revolt.screens.login.LoginGreetingScreen
|
||||
import chat.revolt.screens.login.LoginScreen
|
||||
import chat.revolt.screens.login.MfaScreen
|
||||
import chat.revolt.screens.login2.InitScreen
|
||||
import chat.revolt.screens.main.MainScreen
|
||||
import chat.revolt.screens.register.OnboardingScreen
|
||||
import chat.revolt.screens.register.RegisterDetailsScreen
|
||||
import chat.revolt.screens.register.RegisterGreetingScreen
|
||||
import chat.revolt.screens.register.RegisterVerifyScreen
|
||||
import chat.revolt.screens.services.DiscoverScreen
|
||||
import chat.revolt.screens.settings.AppearanceSettingsScreen
|
||||
import chat.revolt.screens.settings.ChangelogsSettingsScreen
|
||||
import chat.revolt.screens.settings.ChatSettingsScreen
|
||||
import chat.revolt.screens.settings.DebugSettingsScreen
|
||||
import chat.revolt.screens.settings.ExperimentsSettingsScreen
|
||||
import chat.revolt.screens.settings.LanguagePickerSettingsScreen
|
||||
import chat.revolt.screens.settings.ProfileSettingsScreen
|
||||
import chat.revolt.screens.settings.SessionSettingsScreen
|
||||
import chat.revolt.screens.settings.SettingsScreen
|
||||
import chat.revolt.screens.settings.channel.ChannelSettingsHome
|
||||
import chat.revolt.screens.settings.channel.ChannelSettingsOverview
|
||||
import chat.revolt.screens.settings.channel.ChannelSettingsPermissions
|
||||
import chat.revolt.ui.theme.RevoltTheme
|
||||
import chat.peptide.BuildConfig
|
||||
import chat.peptide.R
|
||||
import chat.peptide.PeptideApplication
|
||||
import chat.peptide.api.ApplicationPlatform
|
||||
import chat.peptide.api.HitRateLimitException
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideAPI.setPlatform
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.UrlsStorageKeys
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.routes.microservices.geo.queryGeo
|
||||
import chat.peptide.api.routes.microservices.health.healthCheck
|
||||
import chat.peptide.api.routes.onboard.needsOnboarding
|
||||
import chat.peptide.api.schemas.HealthNotice
|
||||
import chat.peptide.api.settings.Experiments
|
||||
import chat.peptide.api.settings.GeoStateProvider
|
||||
import chat.peptide.api.settings.LoadedSettings
|
||||
import chat.peptide.api.settings.SyncedSettings
|
||||
import chat.peptide.composables.generic.HealthAlert
|
||||
import chat.peptide.composables.generic.PepTextButton
|
||||
import chat.peptide.composables.voice.VoicePermissionSwitch
|
||||
import chat.peptide.composables.voice.VoiceSheet
|
||||
import chat.peptide.material.EasingTokens
|
||||
import chat.peptide.ndk.NativeLibraries
|
||||
import chat.peptide.persistence.KVStorage
|
||||
import chat.peptide.screens.DefaultDestinationScreen
|
||||
import chat.peptide.screens.about.AboutScreen
|
||||
import chat.peptide.screens.about.AttributionScreen
|
||||
import chat.peptide.screens.chat.ChatRouterScreen
|
||||
import chat.peptide.screens.chat.views.channel.ChannelScreen
|
||||
import chat.peptide.screens.chooseplatform.ChoosePlatformScreen
|
||||
import chat.peptide.screens.create.CreateGroupScreen
|
||||
import chat.peptide.screens.labs.LabsRootScreen
|
||||
import chat.peptide.screens.login.LoginGreetingScreen
|
||||
import chat.peptide.screens.login.LoginScreen
|
||||
import chat.peptide.screens.login.MfaScreen
|
||||
import chat.peptide.screens.login2.InitScreen
|
||||
import chat.peptide.screens.main.MainScreen
|
||||
import chat.peptide.screens.register.OnboardingScreen
|
||||
import chat.peptide.screens.register.RegisterDetailsScreen
|
||||
import chat.peptide.screens.register.RegisterGreetingScreen
|
||||
import chat.peptide.screens.register.RegisterVerifyScreen
|
||||
import chat.peptide.screens.services.DiscoverScreen
|
||||
import chat.peptide.screens.settings.AppearanceSettingsScreen
|
||||
import chat.peptide.screens.settings.ChangelogsSettingsScreen
|
||||
import chat.peptide.screens.settings.ChatSettingsScreen
|
||||
import chat.peptide.screens.settings.DebugSettingsScreen
|
||||
import chat.peptide.screens.settings.ExperimentsSettingsScreen
|
||||
import chat.peptide.screens.settings.LanguagePickerSettingsScreen
|
||||
import chat.peptide.screens.settings.ProfileSettingsScreen
|
||||
import chat.peptide.screens.settings.SessionSettingsScreen
|
||||
import chat.peptide.screens.settings.SettingsScreen
|
||||
import chat.peptide.screens.settings.channel.ChannelSettingsHome
|
||||
import chat.peptide.screens.settings.channel.ChannelSettingsOverview
|
||||
import chat.peptide.screens.settings.channel.ChannelSettingsPermissions
|
||||
import chat.peptide.ui.theme.PeptideTheme
|
||||
import chat.peptide.utils.DeepLinkHandler
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.ktor.client.request.get
|
||||
import io.sentry.android.core.SentryAndroid
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@HiltViewModel
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
class MainActivityViewModel @Inject constructor(
|
||||
|
|
@ -165,9 +168,9 @@ class MainActivityViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun canReachRevolt(): Boolean {
|
||||
private suspend fun canReachPeptide(): Boolean {
|
||||
try {
|
||||
val res = RevoltHttp.get("/".api())
|
||||
val res = PeptideHttp.get("/".api())
|
||||
return res.status.value == 200
|
||||
} catch (_: Exception) {
|
||||
return false
|
||||
|
|
@ -197,7 +200,7 @@ class MainActivityViewModel @Inject constructor(
|
|||
|
||||
/**
|
||||
* Sets the default platform on application creation.
|
||||
* It retrieves the platform from key-value storage and sets it in the RevoltAPI.
|
||||
* It retrieves the platform from key-value storage and sets it in the PeptideAPI.
|
||||
* If the platform is not found or invalid, it logs the user out.
|
||||
*/
|
||||
fun setDefaultPlatformOnCreate() {
|
||||
|
|
@ -227,11 +230,11 @@ class MainActivityViewModel @Inject constructor(
|
|||
|
||||
isConnected.emit(hasInternetConnection())
|
||||
|
||||
Log.d("MainActivity", "Checking if we can reach Revolt")
|
||||
Log.d("MainActivity", "Checking if we can reach Peptide")
|
||||
|
||||
if (!isConnected.value) return@launch startWithoutDestination()
|
||||
|
||||
Log.d("MainActivity", "We can reach Revolt, checking if we're logged in")
|
||||
Log.d("MainActivity", "We can reach Peptide, checking if we're logged in")
|
||||
|
||||
val token = kvStorage.get("sessionToken")
|
||||
?: return@launch startWithDestination("choose-platform")
|
||||
|
|
@ -239,17 +242,17 @@ class MainActivityViewModel @Inject constructor(
|
|||
|
||||
Log.d(
|
||||
"MainActivity",
|
||||
"We have a session token, checking if it's valid and if we can still reach Revolt"
|
||||
"We have a session token, checking if it's valid and if we can still reach Peptide"
|
||||
)
|
||||
|
||||
val canReachRevolt = canReachRevolt()
|
||||
val canReachPeptide = canReachPeptide()
|
||||
val valid = try {
|
||||
RevoltAPI.checkSessionToken(token)
|
||||
PeptideAPI.checkSessionToken(token)
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
|
||||
if (canReachRevolt && !valid) {
|
||||
if (canReachPeptide && !valid) {
|
||||
Log.d("MainActivity", "Session token is invalid, could not log in")
|
||||
couldNotLogIn.emit(true)
|
||||
} else {
|
||||
|
|
@ -276,8 +279,8 @@ class MainActivityViewModel @Inject constructor(
|
|||
|
||||
try {
|
||||
Log.d("MainActivity", "Onboarding state is complete, logging in")
|
||||
RevoltAPI.loginAs(token)
|
||||
RevoltAPI.setSessionId(id)
|
||||
PeptideAPI.loginAs(token)
|
||||
PeptideAPI.setSessionId(id)
|
||||
if (Experiments.usePolar.isEnabled) {
|
||||
startWithDestination("main")
|
||||
} else {
|
||||
|
|
@ -352,7 +355,7 @@ class MainActivity : AppCompatActivity() {
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
DynamicColors.applyToActivityIfAvailable(this)
|
||||
DynamicColors.applyToActivitiesIfAvailable(RevoltApplication.instance)
|
||||
DynamicColors.applyToActivitiesIfAvailable(PeptideApplication.instance)
|
||||
@Suppress("DEPRECATION") // We are fixing a bug in the splash screen
|
||||
window.statusBarColor = Color.Transparent.toArgb()
|
||||
}
|
||||
|
|
@ -361,7 +364,7 @@ class MainActivity : AppCompatActivity() {
|
|||
override fun onConfigurationChanged(newConfig: android.content.res.Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
DynamicColors.applyToActivityIfAvailable(this)
|
||||
DynamicColors.applyToActivitiesIfAvailable(RevoltApplication.instance)
|
||||
DynamicColors.applyToActivitiesIfAvailable(PeptideApplication.instance)
|
||||
@Suppress("DEPRECATION") // We are fixing a bug in the splash screen
|
||||
window.statusBarColor = Color.Transparent.toArgb()
|
||||
}
|
||||
|
|
@ -369,20 +372,32 @@ class MainActivity : AppCompatActivity() {
|
|||
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// waiting for view to draw to better represent a captured error with a screenshot
|
||||
findViewById<android.view.View>(android.R.id.content).viewTreeObserver.addOnGlobalLayoutListener {
|
||||
try {
|
||||
throw Exception("This app uses Sentry! :)")
|
||||
} catch (e: Exception) {
|
||||
// Sentry.captureException(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the default platform for the Platform API.
|
||||
viewModel.setDefaultPlatformOnCreate()
|
||||
|
||||
SentryAndroid.init(this) { options ->
|
||||
options.dsn = BuildConfig.SENTRY_DSN
|
||||
options.release = BuildConfig.VERSION_NAME
|
||||
}
|
||||
// SentryAndroid.init(this) { options ->
|
||||
// options.dsn = BuildConfig.SENTRY_DSN
|
||||
// options.release = BuildConfig.VERSION_NAME
|
||||
// }
|
||||
|
||||
@Suppress("DEPRECATION") // We are fixing a bug in the splash screen
|
||||
window.statusBarColor = Color.Transparent.toArgb()
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
RevoltAPI.hydrateFromPersistentCache()
|
||||
PeptideAPI.hydrateFromPersistentCache()
|
||||
|
||||
// Handle deep link data if available
|
||||
handleDeepLinkData(intent)
|
||||
|
||||
setContent {
|
||||
val windowSizeClass = calculateWindowSizeClass(this)
|
||||
|
|
@ -419,6 +434,70 @@ class MainActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
handleDeepLinkData(intent)
|
||||
}
|
||||
|
||||
private fun handleDeepLinkData(intent: Intent) {
|
||||
// Check for deep link data from DeepLinkActivity
|
||||
val channelId = intent.getStringExtra(DeepLinkActivity.PATH_CHANNEL)
|
||||
val serverId = intent.getStringExtra(DeepLinkActivity.PATH_SERVER)
|
||||
val userId = intent.getStringExtra(DeepLinkActivity.PATH_USER)
|
||||
val messageId = intent.getStringExtra(DeepLinkActivity.PATH_MESSAGE)
|
||||
val nextDestination = intent.getStringExtra("next_destination")
|
||||
|
||||
if (nextDestination != null) {
|
||||
Log.d(TAG, "Setting next destination from deep link: $nextDestination")
|
||||
viewModel.updateNextDestination(nextDestination)
|
||||
return
|
||||
}
|
||||
|
||||
// Store deep link data in a static companion object for ChatRouterScreen to access
|
||||
DeepLinkHandler.channelId = channelId
|
||||
DeepLinkHandler.serverId = serverId
|
||||
DeepLinkHandler.userId = userId
|
||||
DeepLinkHandler.messageId = messageId
|
||||
DeepLinkHandler.hasDeepLink = channelId != null || serverId != null || userId != null || messageId != null
|
||||
|
||||
// Wait for the app to be ready before navigating to the deep link destination
|
||||
viewModel.viewModelScope.launch {
|
||||
viewModel.isReady.collect { isReady ->
|
||||
if (isReady) {
|
||||
when {
|
||||
channelId != null -> {
|
||||
Log.d(TAG, "Navigating to channel from deep link: $channelId")
|
||||
// Check if Polar mode is enabled
|
||||
if (Experiments.usePolar.isEnabled) {
|
||||
viewModel.updateNextDestination("main/conversation/$channelId")
|
||||
} else {
|
||||
// For non-Polar mode, we'll use the DeepLinkHandler to communicate with ChatRouterScreen
|
||||
viewModel.updateNextDestination("chat")
|
||||
}
|
||||
}
|
||||
serverId != null -> {
|
||||
Log.d(TAG, "Navigating to server from deep link: $serverId")
|
||||
// Navigate to chat screen, the ChatRouterScreen will handle the server navigation
|
||||
viewModel.updateNextDestination("chat")
|
||||
}
|
||||
userId != null -> {
|
||||
Log.d(TAG, "Navigating to user from deep link: $userId")
|
||||
// Navigate to chat screen, the ChatRouterScreen will handle the user navigation
|
||||
viewModel.updateNextDestination("chat")
|
||||
}
|
||||
messageId != null -> {
|
||||
Log.d(TAG, "Navigating to message from deep link: $messageId")
|
||||
// Navigate to chat screen, the ChatRouterScreen will handle the message navigation
|
||||
viewModel.updateNextDestination("chat")
|
||||
}
|
||||
}
|
||||
// Only collect once
|
||||
return@collect
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProvideKeyboardShortcuts(
|
||||
data: MutableList<KeyboardShortcutGroup>?,
|
||||
menu: Menu?,
|
||||
|
|
@ -444,15 +523,16 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
init {
|
||||
NativeLibraries.init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val RevoltTweenInt: FiniteAnimationSpec<IntOffset> = tween(400, easing = EaseInOutExpo)
|
||||
val RevoltTweenFloat: FiniteAnimationSpec<Float> = tween(400, easing = EaseInOutExpo)
|
||||
val RevoltTweenDp: FiniteAnimationSpec<Dp> = tween(400, easing = EaseInOutExpo)
|
||||
val PeptideTweenInt: FiniteAnimationSpec<IntOffset> = tween(400, easing = EaseInOutExpo)
|
||||
val PeptideTweenFloat: FiniteAnimationSpec<Float> = tween(400, easing = EaseInOutExpo)
|
||||
val PeptideTweenDp: FiniteAnimationSpec<Dp> = tween(400, easing = EaseInOutExpo)
|
||||
|
||||
val NavTweenInt: FiniteAnimationSpec<IntOffset> = tween(350, easing = EaseInOutExpo)
|
||||
val NavTweenFloat: FiniteAnimationSpec<Float> = tween(350, easing = EaseInOutExpo)
|
||||
|
|
@ -502,7 +582,7 @@ fun AppEntrypoint(
|
|||
|
||||
val navController = rememberNavController()
|
||||
|
||||
RevoltTheme(
|
||||
PeptideTheme(
|
||||
requestedTheme = LoadedSettings.theme,
|
||||
colourOverrides = SyncedSettings.android.colourOverrides,
|
||||
) {
|
||||
|
|
@ -536,7 +616,7 @@ fun AppEntrypoint(
|
|||
Text(stringResource(R.string.could_not_log_in_body))
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
PepTextButton(
|
||||
onClick = {
|
||||
onDismissLoginError()
|
||||
onRetryConnection()
|
||||
|
|
@ -546,7 +626,7 @@ fun AppEntrypoint(
|
|||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
PepTextButton(
|
||||
onClick = {
|
||||
onDismissLoginError()
|
||||
onLogout()
|
||||
|
|
@ -645,7 +725,7 @@ fun AppEntrypoint(
|
|||
easing = EasingTokens.EmphasizedDecelerate
|
||||
),
|
||||
initialOffset = { it / 3 }
|
||||
) + fadeIn(animationSpec = RevoltTweenFloat)
|
||||
) + fadeIn(animationSpec = PeptideTweenFloat)
|
||||
}
|
||||
) {
|
||||
ChatRouterScreen(
|
||||
|
|
@ -678,7 +758,7 @@ fun AppEntrypoint(
|
|||
easing = EasingTokens.EmphasizedDecelerate
|
||||
),
|
||||
initialOffset = { it / 3 }
|
||||
) + fadeIn(animationSpec = RevoltTweenFloat) + scaleIn(
|
||||
) + fadeIn(animationSpec = PeptideTweenFloat) + scaleIn(
|
||||
animationSpec = tween(
|
||||
400,
|
||||
easing = EasingTokens.EmphasizedDecelerate
|
||||
|
|
@ -700,7 +780,7 @@ fun AppEntrypoint(
|
|||
easing = EasingTokens.EmphasizedDecelerate
|
||||
),
|
||||
initialOffset = { it }
|
||||
) + fadeIn(animationSpec = RevoltTweenFloat)
|
||||
) + fadeIn(animationSpec = PeptideTweenFloat)
|
||||
},
|
||||
exitTransition = {
|
||||
slideOutOfContainer(
|
||||
|
|
@ -710,7 +790,7 @@ fun AppEntrypoint(
|
|||
easing = EasingTokens.EmphasizedDecelerate
|
||||
),
|
||||
targetOffset = { it }
|
||||
) + fadeOut(animationSpec = RevoltTweenFloat)
|
||||
) + fadeOut(animationSpec = PeptideTweenFloat)
|
||||
}
|
||||
) { backStackEntry ->
|
||||
val channelId = backStackEntry.arguments?.getString("channelId") ?: ""
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.activities
|
||||
package chat.peptide.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
|
|
@ -50,25 +50,25 @@ import androidx.documentfile.provider.DocumentFile
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.ChannelUtils
|
||||
import chat.revolt.api.routes.channel.sendMessage
|
||||
import chat.revolt.api.routes.microservices.autumn.FileArgs
|
||||
import chat.revolt.api.routes.microservices.autumn.MAX_ATTACHMENTS_PER_MESSAGE
|
||||
import chat.revolt.api.routes.microservices.autumn.uploadToAutumn
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.revolt.api.settings.LoadedSettings
|
||||
import chat.revolt.api.settings.SyncedSettings
|
||||
import chat.revolt.composables.chat.MessageField
|
||||
import chat.revolt.composables.emoji.EmojiPicker
|
||||
import chat.revolt.composables.screens.chat.AttachmentManager
|
||||
import chat.revolt.composables.screens.chat.drawer.ChannelItem
|
||||
import chat.revolt.composables.screens.chat.drawer.ChannelItemIconType
|
||||
import chat.revolt.composables.screens.chat.drawer.DMOrGroupItem
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.revolt.screens.chat.views.channel.ChannelScreenActivePane
|
||||
import chat.revolt.ui.theme.RevoltTheme
|
||||
import chat.peptide.R
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.ChannelUtils
|
||||
import chat.peptide.api.routes.channel.sendMessage
|
||||
import chat.peptide.api.routes.microservices.autumn.FileArgs
|
||||
import chat.peptide.api.routes.microservices.autumn.MAX_ATTACHMENTS_PER_MESSAGE
|
||||
import chat.peptide.api.routes.microservices.autumn.uploadToAutumn
|
||||
import chat.peptide.api.schemas.ChannelType
|
||||
import chat.peptide.api.settings.LoadedSettings
|
||||
import chat.peptide.api.settings.SyncedSettings
|
||||
import chat.peptide.composables.chat.MessageField
|
||||
import chat.peptide.composables.emoji.EmojiPicker
|
||||
import chat.peptide.composables.screens.chat.AttachmentManager
|
||||
import chat.peptide.composables.screens.chat.drawer.ChannelItem
|
||||
import chat.peptide.composables.screens.chat.drawer.ChannelItemIconType
|
||||
import chat.peptide.composables.screens.chat.drawer.DMOrGroupItem
|
||||
import chat.peptide.persistence.KVStorage
|
||||
import chat.peptide.screens.chat.views.channel.ChannelScreenActivePane
|
||||
import chat.peptide.ui.theme.PeptideTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.ktor.http.ContentType
|
||||
|
|
@ -180,10 +180,10 @@ class ShareTargetScreenViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
suspend fun initialiseAPI() {
|
||||
if (!RevoltAPI.isLoggedIn()) {
|
||||
if (!PeptideAPI.isLoggedIn()) {
|
||||
val token = kvStorage.get("sessionToken") ?: return
|
||||
RevoltAPI.loginAs(token)
|
||||
RevoltAPI.initialize()
|
||||
PeptideAPI.loginAs(token)
|
||||
PeptideAPI.initialize()
|
||||
}
|
||||
apiIsReady = true
|
||||
}
|
||||
|
|
@ -207,7 +207,7 @@ class ShareTargetScreenViewModel @Inject constructor(
|
|||
}
|
||||
)
|
||||
attachmentIds.add(id)
|
||||
} catch (e: Exception) {
|
||||
} catch (_: Exception) {
|
||||
return@launch
|
||||
}
|
||||
}
|
||||
|
|
@ -277,7 +277,7 @@ fun ShareTargetScreen(
|
|||
var channelSearchContent by remember { mutableStateOf("") }
|
||||
var selectedChannel by rememberSaveable { mutableStateOf<String?>(null) }
|
||||
|
||||
RevoltTheme(
|
||||
PeptideTheme(
|
||||
requestedTheme = LoadedSettings.theme,
|
||||
colourOverrides = SyncedSettings.android.colourOverrides
|
||||
) {
|
||||
|
|
@ -326,7 +326,7 @@ fun ShareTargetScreen(
|
|||
Box(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
val filteredChannels = RevoltAPI.channelCache.values.asSequence().filter {
|
||||
val filteredChannels = PeptideAPI.channelCache.values.asSequence().filter {
|
||||
it.name?.contains(
|
||||
channelSearchContent,
|
||||
ignoreCase = true
|
||||
|
|
@ -346,12 +346,13 @@ fun ShareTargetScreen(
|
|||
ChannelType.Group, ChannelType.DirectMessage -> DMOrGroupItem(
|
||||
channel = channel,
|
||||
partner = ChannelUtils.resolveDMPartner(channel)?.let { u ->
|
||||
RevoltAPI.userCache[u]
|
||||
PeptideAPI.userCache[u]
|
||||
},
|
||||
isCurrent = selectedChannel == channel.id,
|
||||
hasUnread = false,
|
||||
onDestinationChanged = { selectedChannel = channel.id },
|
||||
onOpenChannelContextSheet = {}
|
||||
onOpenChannelContextSheet = {},
|
||||
onOpenUserInfoSheet = {_ ->}
|
||||
)
|
||||
|
||||
else -> ChannelItem(
|
||||
|
|
@ -421,9 +422,9 @@ fun ShareTargetScreen(
|
|||
}
|
||||
}
|
||||
},
|
||||
channelType = RevoltAPI.channelCache[selectedChannel]?.channelType
|
||||
channelType = PeptideAPI.channelCache[selectedChannel]?.channelType
|
||||
?: ChannelType.TextChannel,
|
||||
channelName = RevoltAPI.channelCache[selectedChannel]?.name ?: "",
|
||||
channelName = PeptideAPI.channelCache[selectedChannel]?.name ?: "",
|
||||
)
|
||||
|
||||
AnimatedVisibility(viewModel.activeBottomPane is ChannelScreenActivePane.EmojiPicker) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.activities.media
|
||||
package chat.peptide.activities.media
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Intent
|
||||
|
|
@ -40,14 +40,14 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.core.view.WindowCompat
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.schemas.AutumnResource
|
||||
import chat.revolt.api.settings.LoadedSettings
|
||||
import chat.revolt.api.settings.SyncedSettings
|
||||
import chat.revolt.providers.getAttachmentContentUri
|
||||
import chat.revolt.ui.theme.RevoltTheme
|
||||
import chat.peptide.R
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.schemas.AutumnResource
|
||||
import chat.peptide.api.settings.LoadedSettings
|
||||
import chat.peptide.api.settings.SyncedSettings
|
||||
import chat.peptide.providers.getAttachmentContentUri
|
||||
import chat.peptide.ui.theme.PeptideTheme
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.readBytes
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -85,7 +85,7 @@ class ImageViewActivity : ComponentActivity() {
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
|
||||
val resourceUrl = "${RevoltAPI.getCurrentFilesUrl()}/attachments/${resource.id}/${resource.filename}"
|
||||
val resourceUrl = "${PeptideAPI.getCurrentFilesUrl()}/attachments/${resource.id}/${resource.filename}"
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
|
|
@ -145,13 +145,13 @@ fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
|
|||
ContentValues().apply {
|
||||
put(MediaStore.Images.Media.DISPLAY_NAME, resource.filename)
|
||||
put(MediaStore.Images.Media.MIME_TYPE, resource.contentType)
|
||||
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/Revolt")
|
||||
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/Peptide")
|
||||
put(MediaStore.Images.Media.IS_PENDING, 1)
|
||||
}
|
||||
)
|
||||
}?.let { uri ->
|
||||
context.contentResolver.openOutputStream(uri).use { stream ->
|
||||
val image = RevoltHttp.get(resourceUrl).readBytes()
|
||||
val image = PeptideHttp.get(resourceUrl).readBytes()
|
||||
stream?.write(image)
|
||||
|
||||
context.applicationContext.let {
|
||||
|
|
@ -182,7 +182,7 @@ fun ImageViewScreen(resource: AutumnResource, onClose: () -> Unit = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
RevoltTheme(
|
||||
PeptideTheme(
|
||||
requestedTheme = LoadedSettings.theme,
|
||||
colourOverrides = SyncedSettings.android.colourOverrides
|
||||
) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.activities.media
|
||||
package chat.peptide.activities.media
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Intent
|
||||
|
|
@ -18,12 +18,12 @@ import androidx.fragment.app.FragmentActivity
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.schemas.AutumnResource
|
||||
import chat.revolt.databinding.ActivityVideoplayerBinding
|
||||
import chat.revolt.providers.getAttachmentContentUri
|
||||
import chat.peptide.R
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.schemas.AutumnResource
|
||||
import chat.peptide.databinding.ActivityVideoplayerBinding
|
||||
import chat.peptide.providers.getAttachmentContentUri
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import io.ktor.client.request.get
|
||||
|
|
@ -54,7 +54,7 @@ class VideoViewActivity : FragmentActivity() {
|
|||
}
|
||||
|
||||
val resourceUrl =
|
||||
"${RevoltAPI.getCurrentFilesUrl()}/attachments/${autumnResource.id}/${autumnResource.filename}"
|
||||
"${PeptideAPI.getCurrentFilesUrl()}/attachments/${autumnResource.id}/${autumnResource.filename}"
|
||||
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
|
|
@ -189,13 +189,13 @@ class VideoViewActivity : FragmentActivity() {
|
|||
ContentValues().apply {
|
||||
put(MediaStore.Video.Media.DISPLAY_NAME, resource.filename)
|
||||
put(MediaStore.Video.Media.MIME_TYPE, resource.contentType)
|
||||
put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/Revolt")
|
||||
put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/Peptide")
|
||||
put(MediaStore.Video.Media.IS_PENDING, 1)
|
||||
}
|
||||
)
|
||||
}?.let { uri ->
|
||||
this@VideoViewActivity.contentResolver.openOutputStream(uri).use { stream ->
|
||||
val video = RevoltHttp.get(resourceUrl).readBytes()
|
||||
val video = PeptideHttp.get(resourceUrl).readBytes()
|
||||
stream?.write(video)
|
||||
|
||||
this@VideoViewActivity.applicationContext.let {
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
package chat.revolt.api
|
||||
package chat.peptide.api
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import chat.revolt.BuildConfig
|
||||
import chat.revolt.RevoltApplication
|
||||
import chat.revolt.api.RevoltAPI.initialize
|
||||
import chat.revolt.api.internals.Members
|
||||
import chat.revolt.api.realtime.DisconnectionState
|
||||
import chat.revolt.api.realtime.RealtimeSocket
|
||||
import chat.revolt.api.routes.user.fetchSelf
|
||||
import chat.revolt.api.schemas.AutumnResource
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.revolt.api.schemas.Emoji
|
||||
import chat.revolt.api.schemas.Message
|
||||
import chat.revolt.api.schemas.Server
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.revolt.api.unreads.Unreads
|
||||
import chat.revolt.getKVStorage
|
||||
import chat.revolt.persistence.Database
|
||||
import chat.revolt.persistence.SqlStorage
|
||||
import chat.peptide.BuildConfig
|
||||
import chat.peptide.PeptideApplication
|
||||
import chat.peptide.api.PeptideAPI.initialize
|
||||
import chat.peptide.api.internals.Members
|
||||
import chat.peptide.api.realtime.DisconnectionState
|
||||
import chat.peptide.api.realtime.RealtimeSocket
|
||||
import chat.peptide.api.routes.user.fetchSelf
|
||||
import chat.peptide.api.schemas.AutumnResource
|
||||
import chat.peptide.api.schemas.ChannelType
|
||||
import chat.peptide.api.schemas.Emoji
|
||||
import chat.peptide.api.schemas.Message
|
||||
import chat.peptide.api.schemas.Server
|
||||
import chat.peptide.api.schemas.User
|
||||
import chat.peptide.api.unreads.Unreads
|
||||
import chat.peptide.getKVStorage
|
||||
import chat.peptide.persistence.Database
|
||||
import chat.peptide.persistence.SqlStorage
|
||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||
import com.chuckerteam.chucker.api.RetentionManager
|
||||
|
|
@ -35,7 +35,6 @@ import io.ktor.client.plugins.logging.Logging
|
|||
import io.ktor.client.plugins.websocket.WebSockets
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.sentry.Sentry
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -52,13 +51,13 @@ import kotlinx.serialization.Serializable
|
|||
import kotlinx.serialization.cbor.Cbor
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.net.SocketException
|
||||
import chat.revolt.api.schemas.Channel as ChannelSchema
|
||||
import chat.peptide.api.schemas.Channel as ChannelSchema
|
||||
|
||||
/**
|
||||
* Enum representing available platforms in the application.
|
||||
*/
|
||||
enum class ApplicationPlatform(val baseUrl: String) {
|
||||
REVOLT("https://api.revolt.chat"),
|
||||
REVOLT("https://api.peptide.chat"),
|
||||
PEP("https://peptide.chat/api");
|
||||
|
||||
companion object {
|
||||
|
|
@ -117,7 +116,7 @@ object UrlsStorageKeys {
|
|||
}
|
||||
|
||||
fun String.api(): String {
|
||||
return "${RevoltAPI.getCurrentBaseUrl()}$this"
|
||||
return "${PeptideAPI.getCurrentBaseUrl()}$this"
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -128,27 +127,27 @@ private fun getUrlForPlatform(platform: ApplicationPlatform, urlSelector: (Platf
|
|||
}
|
||||
|
||||
fun buildUserAgent(accessMethod: String = "Ktor"): String {
|
||||
return "$accessMethod RevoltAndroid/${BuildConfig.VERSION_NAME} " +
|
||||
return "$accessMethod PeptideAndroid/${BuildConfig.VERSION_NAME} " +
|
||||
"${BuildConfig.APPLICATION_ID} Android/${android.os.Build.VERSION.SDK_INT} " +
|
||||
"(${android.os.Build.MANUFACTURER} ${android.os.Build.DEVICE}) Kotlin/${KotlinVersion.CURRENT}"
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
val RevoltJson = Json {
|
||||
val PeptideJson = Json {
|
||||
ignoreUnknownKeys = true
|
||||
explicitNulls = false
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
val RevoltCbor = Cbor {
|
||||
val PeptideCbor = Cbor {
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
val RevoltHttp by lazy {
|
||||
val PeptideHttp by lazy {
|
||||
HttpClient(OkHttp) {
|
||||
install(DefaultRequest)
|
||||
install(ContentNegotiation) {
|
||||
json(RevoltJson)
|
||||
json(PeptideJson)
|
||||
}
|
||||
|
||||
install(WebSockets)
|
||||
|
|
@ -167,15 +166,15 @@ val RevoltHttp by lazy {
|
|||
install(Logging) { level = LogLevel.INFO }
|
||||
|
||||
val chuckerCollector = ChuckerCollector(
|
||||
context = RevoltApplication.instance,
|
||||
context = PeptideApplication.instance,
|
||||
showNotification = true,
|
||||
retentionPeriod = RetentionManager.Period.ONE_DAY
|
||||
)
|
||||
|
||||
val chuckerInterceptor = ChuckerInterceptor.Builder(RevoltApplication.instance)
|
||||
val chuckerInterceptor = ChuckerInterceptor.Builder(PeptideApplication.instance)
|
||||
.collector(chuckerCollector)
|
||||
.maxContentLength(250_000L)
|
||||
.redactHeaders(RevoltAPI.TOKEN_HEADER_NAME)
|
||||
.redactHeaders(PeptideAPI.TOKEN_HEADER_NAME)
|
||||
.alwaysReadResponseBody(true)
|
||||
.createShortcut(false)
|
||||
.build()
|
||||
|
|
@ -184,8 +183,8 @@ val RevoltHttp by lazy {
|
|||
addInterceptor { chain ->
|
||||
val request = chain.request().newBuilder()
|
||||
.apply {
|
||||
if (chain.request().headers[RevoltAPI.TOKEN_HEADER_NAME] == null) {
|
||||
header(RevoltAPI.TOKEN_HEADER_NAME, RevoltAPI.sessionToken)
|
||||
if (chain.request().headers[PeptideAPI.TOKEN_HEADER_NAME] == null) {
|
||||
header(PeptideAPI.TOKEN_HEADER_NAME, PeptideAPI.sessionToken)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
|
@ -195,7 +194,7 @@ val RevoltHttp by lazy {
|
|||
}
|
||||
|
||||
defaultRequest {
|
||||
url(RevoltAPI.getCurrentBaseUrl())
|
||||
url(PeptideAPI.getCurrentBaseUrl())
|
||||
header("User-Agent", buildUserAgent())
|
||||
}
|
||||
}
|
||||
|
|
@ -203,7 +202,7 @@ val RevoltHttp by lazy {
|
|||
|
||||
val mainHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
object RevoltAPI {
|
||||
object PeptideAPI {
|
||||
const val TOKEN_HEADER_NAME = "x-session-token"
|
||||
|
||||
val userCache = mutableStateMapOf<String, User>()
|
||||
|
|
@ -245,7 +244,7 @@ object RevoltAPI {
|
|||
* Saves the current platform selection to persistent storage.
|
||||
*/
|
||||
private suspend fun savePlatformSelection() {
|
||||
val kvStorage = RevoltApplication.instance.getKVStorage()
|
||||
val kvStorage = PeptideApplication.instance.getKVStorage()
|
||||
kvStorage.set(UrlsStorageKeys.PLATFORM, selectedApplicationPlatform.name)
|
||||
}
|
||||
|
||||
|
|
@ -253,7 +252,7 @@ object RevoltAPI {
|
|||
* Loads the platform selection from persistent storage.
|
||||
*/
|
||||
suspend fun loadPlatformSelection() {
|
||||
val kvStorage = RevoltApplication.instance.getKVStorage()
|
||||
val kvStorage = PeptideApplication.instance.getKVStorage()
|
||||
val applicationPlatformName = kvStorage.get(UrlsStorageKeys.PLATFORM) ?: ApplicationPlatform.REVOLT.name
|
||||
selectedApplicationPlatform = try {
|
||||
ApplicationPlatform.valueOf(applicationPlatformName)
|
||||
|
|
@ -304,23 +303,23 @@ object RevoltAPI {
|
|||
try {
|
||||
RealtimeSocket.connect(sessionToken)
|
||||
} catch (e: SocketException) {
|
||||
Log.d("RevoltAPI", "Socket closed, probably no big deal /// " + e.message)
|
||||
Log.d("PeptideAPI", "Socket closed, probably no big deal /// " + e.message)
|
||||
RealtimeSocket.updateDisconnectionState(DisconnectionState.Disconnected)
|
||||
} catch (e: Exception) {
|
||||
Log.e("RevoltAPI", "WebSocket error", e)
|
||||
Log.e("PeptideAPI", "WebSocket error", e)
|
||||
RealtimeSocket.updateDisconnectionState(DisconnectionState.Disconnected)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
if (e is InterruptedException) {
|
||||
Log.d("RevoltAPI", "Socket interrupted")
|
||||
Log.d("PeptideAPI", "Socket interrupted")
|
||||
} else {
|
||||
Log.e("RevoltAPI", "WebSocket error", e)
|
||||
Log.e("PeptideAPI", "WebSocket error", e)
|
||||
}
|
||||
RealtimeSocket.updateDisconnectionState(DisconnectionState.Disconnected)
|
||||
} catch (e: Exception) {
|
||||
Sentry.captureMessage("Error in socket error handling: $e")
|
||||
// Sentry.captureMessage("Error in socket error handling: $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -330,7 +329,7 @@ object RevoltAPI {
|
|||
connectWS()
|
||||
|
||||
// Send a ping every roughly 30 seconds else the socket dies
|
||||
// Same interval as the web clients (/revolt.js)
|
||||
// Same interval as the web clients (/peptide.js)
|
||||
// Note: This will run even if the socket is closed (sendPing will just exit early)
|
||||
mainHandler.post(object : Runnable {
|
||||
override fun run() {
|
||||
|
|
@ -398,9 +397,9 @@ object RevoltAPI {
|
|||
*/
|
||||
fun hydrateFromPersistentCache() {
|
||||
if (!openForLocalHydration) {
|
||||
Log.w("RevoltAPI", "Hydration is closed, but was called")
|
||||
Log.w("PeptideAPI", "Hydration is closed, but was called")
|
||||
// Stale data is worst case, let's track it even in prod
|
||||
Sentry.captureMessage("Local hydration called twice or after real data was fetched")
|
||||
// Sentry.captureMessage("Local hydration called twice or after real data was fetched")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -476,7 +475,7 @@ object RevoltAPI {
|
|||
}
|
||||
|
||||
@Serializable
|
||||
data class RevoltError(val type: String)
|
||||
data class PeptideError(val type: String)
|
||||
|
||||
@Serializable
|
||||
data class RateLimitResponse(@SerialName("retry_after") val retryAfter: Int) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
|
|
@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.Brush.Companion.linearGradient
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.core.graphics.toColorInt
|
||||
import chat.revolt.api.internals.colour.CSSColours
|
||||
import chat.peptide.api.internals.colour.CSSColours
|
||||
|
||||
fun Brush.Companion.solidColor(colour: Color) = SolidColor(colour)
|
||||
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.schemas.Channel
|
||||
import chat.revolt.api.schemas.Server
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import chat.peptide.api.schemas.Server
|
||||
import chat.peptide.api.schemas.User
|
||||
|
||||
sealed class CategorisedChannelList {
|
||||
data class Channel(val channel: chat.revolt.api.schemas.Channel) : CategorisedChannelList()
|
||||
data class Category(val category: chat.revolt.api.schemas.Category) : CategorisedChannelList()
|
||||
data class Channel(val channel: chat.peptide.api.schemas.Channel) : CategorisedChannelList()
|
||||
data class Category(val category: chat.peptide.api.schemas.Category) : CategorisedChannelList()
|
||||
}
|
||||
|
||||
object ChannelUtils {
|
||||
|
|
@ -19,7 +19,7 @@ object ChannelUtils {
|
|||
*/
|
||||
fun resolveName(channel: Channel): String? {
|
||||
return channel.name
|
||||
?: RevoltAPI.userCache[channel.recipients?.first { u -> u != RevoltAPI.selfId }]?.let {
|
||||
?: PeptideAPI.userCache[channel.recipients?.first { u -> u != PeptideAPI.selfId }]?.let {
|
||||
User.resolveDefaultName(
|
||||
it
|
||||
)
|
||||
|
|
@ -27,7 +27,7 @@ object ChannelUtils {
|
|||
}
|
||||
|
||||
fun resolveDMPartner(channel: Channel): String? {
|
||||
return channel.recipients?.firstOrNull { u -> u != RevoltAPI.selfId }
|
||||
return channel.recipients?.firstOrNull { u -> u != PeptideAPI.selfId }
|
||||
}
|
||||
|
||||
fun categoriseServerFlat(server: Server): List<CategorisedChannelList> {
|
||||
|
|
@ -42,7 +42,7 @@ object ChannelUtils {
|
|||
} ?: true
|
||||
}
|
||||
?.mapNotNull {
|
||||
RevoltAPI.channelCache[it]?.let { it1 ->
|
||||
PeptideAPI.channelCache[it]?.let { it1 ->
|
||||
CategorisedChannelList.Channel(it1)
|
||||
}
|
||||
} ?: emptyList()
|
||||
|
|
@ -53,7 +53,7 @@ object ChannelUtils {
|
|||
categories.forEach {
|
||||
output.add(it)
|
||||
val channels = it.category.channels?.mapNotNull { c ->
|
||||
RevoltAPI.channelCache[c]?.let { it1 ->
|
||||
PeptideAPI.channelCache[c]?.let { it1 ->
|
||||
CategorisedChannelList.Channel(it1)
|
||||
}
|
||||
} ?: emptyList()
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.SpecialUsers.PLATFORM_MODERATION_USER
|
||||
import chat.revolt.api.schemas.Channel
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.SpecialUsers.PLATFORM_MODERATION_USER
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import chat.peptide.api.schemas.ChannelType
|
||||
|
||||
object DirectMessages {
|
||||
fun unreadDMs(): List<Channel> {
|
||||
return RevoltAPI.channelCache.values
|
||||
return PeptideAPI.channelCache.values
|
||||
.filter {
|
||||
it.channelType in listOf(
|
||||
ChannelType.DirectMessage, ChannelType.Group
|
||||
|
|
@ -15,7 +15,7 @@ object DirectMessages {
|
|||
}
|
||||
.filter {
|
||||
it.id?.let { id ->
|
||||
RevoltAPI.unreads.hasUnread(
|
||||
PeptideAPI.unreads.hasUnread(
|
||||
id,
|
||||
it.lastMessageID!!,
|
||||
serverId = null
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
|
|
@ -1,35 +1,35 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.schemas.User
|
||||
|
||||
object FriendRequests {
|
||||
fun getIncoming(): List<User> {
|
||||
return RevoltAPI.userCache.values.filter { user ->
|
||||
return PeptideAPI.userCache.values.filter { user ->
|
||||
user.relationship == "Incoming"
|
||||
}
|
||||
}
|
||||
|
||||
fun getOutgoing(): List<User> {
|
||||
return RevoltAPI.userCache.values.filter { user ->
|
||||
return PeptideAPI.userCache.values.filter { user ->
|
||||
user.relationship == "Outgoing"
|
||||
}
|
||||
}
|
||||
|
||||
fun getBlocked(): List<User> {
|
||||
return RevoltAPI.userCache.values.filter { user ->
|
||||
return PeptideAPI.userCache.values.filter { user ->
|
||||
user.relationship == "Blocked"
|
||||
}
|
||||
}
|
||||
|
||||
fun getOnlineFriends(): List<User> {
|
||||
return RevoltAPI.userCache.values.filter { user ->
|
||||
return PeptideAPI.userCache.values.filter { user ->
|
||||
user.relationship == "Friend" && user.online == true
|
||||
}
|
||||
}
|
||||
|
||||
fun getFriends(excludeOnline: Boolean = false): List<User> {
|
||||
return RevoltAPI.userCache.values.filter { user ->
|
||||
return PeptideAPI.userCache.values.filter { user ->
|
||||
user.relationship == "Friend" && if (excludeOnline) user.online == false else true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import chat.revolt.api.schemas.Member
|
||||
import chat.peptide.api.schemas.Member
|
||||
|
||||
class Members {
|
||||
// memberCache (mapping of serverId to userId to member)
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
/**
|
||||
* Flags for messages that can be set to modify their behavior.
|
||||
*
|
||||
* See [Reference](https://docs.rs/revolt-models/latest/revolt_models/v0/enum.MessageFlags.html) for
|
||||
* See [Reference](https://docs.rs/peptide-models/latest/peptide_models/v0/enum.MessageFlags.html) for
|
||||
* values
|
||||
*
|
||||
* `shl 0` is not used.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
enum class PermissionBit(val value: Long) {
|
||||
// * Generic permissions
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.User
|
||||
|
||||
object ResourceLocations {
|
||||
fun userAvatarUrl(user: User?): String {
|
||||
if (user?.avatar != null) {
|
||||
return "${RevoltAPI.getCurrentFilesUrl()}/avatars/${user.avatar.id}"
|
||||
return "${PeptideAPI.getCurrentFilesUrl()}/avatars/${user.avatar.id}"
|
||||
}
|
||||
return "/users/${(user?.id ?: "").ifBlank { "0".repeat(26) }}/default_avatar".api()
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.schemas.Channel
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.revolt.api.schemas.Member
|
||||
import chat.revolt.api.schemas.PermissionDescription
|
||||
import chat.revolt.api.schemas.Role
|
||||
import chat.revolt.api.schemas.Server
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import chat.peptide.api.schemas.ChannelType
|
||||
import chat.peptide.api.schemas.Member
|
||||
import chat.peptide.api.schemas.PermissionDescription
|
||||
import chat.peptide.api.schemas.Role
|
||||
import chat.peptide.api.schemas.Server
|
||||
import chat.peptide.api.schemas.User
|
||||
import kotlinx.datetime.Clock
|
||||
|
||||
object Roles {
|
||||
|
|
@ -27,8 +27,8 @@ object Roles {
|
|||
withColour: Boolean = false,
|
||||
hoisted: Boolean = false
|
||||
): Role? {
|
||||
val server = RevoltAPI.serverCache[serverId] ?: return null
|
||||
val member = RevoltAPI.members.getMember(serverId, userId) ?: return null
|
||||
val server = PeptideAPI.serverCache[serverId] ?: return null
|
||||
val member = PeptideAPI.members.getMember(serverId, userId) ?: return null
|
||||
|
||||
val roles = member.roles?.map { roleId ->
|
||||
server.roles?.get(roleId)
|
||||
|
|
@ -43,13 +43,13 @@ object Roles {
|
|||
}
|
||||
|
||||
fun inOrder(serverId: String, predicate: (Role) -> Boolean): List<Role> {
|
||||
val server = RevoltAPI.serverCache[serverId] ?: return emptyList()
|
||||
val server = PeptideAPI.serverCache[serverId] ?: return emptyList()
|
||||
|
||||
return server.roles?.values?.filter(predicate)?.sortedBy { it.rank } ?: emptyList()
|
||||
}
|
||||
|
||||
fun permissionFor(server: Server, member: Member): Long {
|
||||
val user = RevoltAPI.userCache[member.id?.user] ?: return 0L
|
||||
val user = PeptideAPI.userCache[member.id?.user] ?: return 0L
|
||||
|
||||
if (user.privileged == true) return PermissionBit.GrantAllSafe.value
|
||||
if (server.owner == member.id?.user) return PermissionBit.GrantAllSafe.value
|
||||
|
|
@ -71,7 +71,7 @@ object Roles {
|
|||
}
|
||||
|
||||
// TODO may not be exactly accurate
|
||||
// See https://github.com/revoltchat/revolt.js/blob/2ba023c879b2a53f9a3cc7042e6721c28dd970ba/src/permissions/calculator.ts#L80-L158
|
||||
// See https://github.com/peptidechat/peptide.js/blob/2ba023c879b2a53f9a3cc7042e6721c28dd970ba/src/permissions/calculator.ts#L80-L158
|
||||
fun permissionFor(channel: Channel, user: User? = null, member: Member? = null): Long {
|
||||
return when (channel.channelType) {
|
||||
ChannelType.SavedMessages -> BitDefaults.SavedMessages
|
||||
|
|
@ -80,13 +80,13 @@ object Roles {
|
|||
ChannelType.Group -> if (channel.owner == user?.id) PermissionBit.GrantAllSafe.value else BitDefaults.DirectMessages
|
||||
|
||||
ChannelType.TextChannel, ChannelType.VoiceChannel -> {
|
||||
val server = RevoltAPI.serverCache[channel.server]
|
||||
val server = PeptideAPI.serverCache[channel.server]
|
||||
// FIXME this is a stupid patch to prevent it from showing "no permission" on a channel on launch
|
||||
?: return PermissionBit.GrantAllSafe.value
|
||||
|
||||
if (server.owner == user?.id) return PermissionBit.GrantAllSafe.value
|
||||
|
||||
val chMember = member ?: RevoltAPI.members.getMember(
|
||||
val chMember = member ?: PeptideAPI.members.getMember(
|
||||
server.id ?: return 0L,
|
||||
user?.id ?: return 0L
|
||||
) ?: return 0L
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.RuntimeShader
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import android.graphics.LinearGradient
|
||||
import android.graphics.Shader
|
||||
|
|
@ -6,7 +6,7 @@ import android.util.Log
|
|||
import android.widget.TextView
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.core.graphics.toColorInt
|
||||
import chat.revolt.api.internals.colour.CSSColours
|
||||
import chat.peptide.api.internals.colour.CSSColours
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.elevation.SurfaceColors
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -26,7 +26,7 @@ fun Color.asHexJsonPrimitiveString(): JsonPrimitive {
|
|||
object ThemeCompat {
|
||||
@Composable
|
||||
fun materialThemeAsDiscoverTheme(materialTheme: MaterialTheme): JsonObject {
|
||||
// https://github.com/revoltchat/discover/blob/6effdf4a611e89b38b5e6bccefa1cd999e4b545f/styles/variables.scss
|
||||
// https://github.com/peptidechat/discover/blob/6effdf4a611e89b38b5e6bccefa1cd999e4b545f/styles/variables.scss
|
||||
return JsonObject(
|
||||
mapOf(
|
||||
"accent" to materialTheme.colorScheme.primary.asHexJsonPrimitiveString(),
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import kotlin.experimental.and
|
||||
import kotlin.random.Random
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package chat.revolt.api.internals
|
||||
package chat.peptide.api.internals
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import chat.revolt.api.RevoltCbor
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideCbor
|
||||
import chat.peptide.api.schemas.User
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.io.encoding.Base64
|
||||
|
|
@ -21,8 +21,8 @@ data class UserQRContents(
|
|||
object UserQR {
|
||||
@OptIn(ExperimentalSerializationApi::class, ExperimentalEncodingApi::class)
|
||||
fun contents(user: User): String {
|
||||
return "https://revolt.chat/qr?" + Base64.encode(
|
||||
RevoltCbor.encodeToByteArray(
|
||||
return "https://peptide.chat/qr?" + Base64.encode(
|
||||
PeptideCbor.encodeToByteArray(
|
||||
UserQRContents.serializer(),
|
||||
UserQRContents(
|
||||
format = "rqr\$user\$0",
|
||||
|
|
@ -45,7 +45,7 @@ object UserQR {
|
|||
val uri = uriString.toUri()
|
||||
val base64 = uri.query ?: return null
|
||||
val decodedBytes = Base64.decode(base64)
|
||||
RevoltCbor.decodeFromByteArray(UserQRContents.serializer(), decodedBytes)
|
||||
PeptideCbor.decodeFromByteArray(UserQRContents.serializer(), decodedBytes)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.internals.colour
|
||||
package chat.peptide.api.internals.colour
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
|
|
@ -1,48 +1,48 @@
|
|||
package chat.revolt.api.realtime
|
||||
package chat.peptide.api.realtime
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import chat.revolt.RevoltApplication
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.realtime.frames.receivable.AnyFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.BulkFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ChannelAckFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ChannelDeleteFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ChannelStartTypingFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ChannelStopTypingFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ChannelUpdateFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.MessageAppendFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.MessageDeleteFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.MessageFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.MessageReactFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.MessageUpdateFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.PongFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ReadyFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerCreateFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerDeleteFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerMemberJoinFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerMemberLeaveFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerMemberUpdateFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerRoleDeleteFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerRoleUpdateFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.ServerUpdateFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.UserRelationshipFrame
|
||||
import chat.revolt.api.realtime.frames.receivable.UserUpdateFrame
|
||||
import chat.revolt.api.realtime.frames.sendable.AuthorizationFrame
|
||||
import chat.revolt.api.realtime.frames.sendable.BeginTypingFrame
|
||||
import chat.revolt.api.realtime.frames.sendable.EndTypingFrame
|
||||
import chat.revolt.api.realtime.frames.sendable.PingFrame
|
||||
import chat.revolt.api.routes.server.fetchMember
|
||||
import chat.revolt.api.schemas.Channel
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.revolt.api.schemas.Role
|
||||
import chat.revolt.api.settings.LoadedSettings
|
||||
import chat.revolt.api.settings.SyncedSettings
|
||||
import chat.revolt.c2dm.ChannelRegistrator
|
||||
import chat.revolt.persistence.Database
|
||||
import chat.revolt.persistence.SqlStorage
|
||||
import chat.peptide.PeptideApplication
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.realtime.frames.receivable.AnyFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.BulkFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ChannelAckFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ChannelDeleteFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ChannelStartTypingFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ChannelStopTypingFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ChannelUpdateFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.MessageAppendFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.MessageDeleteFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.MessageFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.MessageReactFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.MessageUpdateFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.PongFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ReadyFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerCreateFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerDeleteFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerMemberJoinFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerMemberLeaveFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerMemberUpdateFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerRoleDeleteFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerRoleUpdateFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.ServerUpdateFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.UserRelationshipFrame
|
||||
import chat.peptide.api.realtime.frames.receivable.UserUpdateFrame
|
||||
import chat.peptide.api.realtime.frames.sendable.AuthorizationFrame
|
||||
import chat.peptide.api.realtime.frames.sendable.BeginTypingFrame
|
||||
import chat.peptide.api.realtime.frames.sendable.EndTypingFrame
|
||||
import chat.peptide.api.realtime.frames.sendable.PingFrame
|
||||
import chat.peptide.api.routes.server.fetchMember
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import chat.peptide.api.schemas.ChannelType
|
||||
import chat.peptide.api.schemas.Role
|
||||
import chat.peptide.api.settings.LoadedSettings
|
||||
import chat.peptide.api.settings.SyncedSettings
|
||||
import chat.peptide.c2dm.ChannelRegistrator
|
||||
import chat.peptide.persistence.Database
|
||||
import chat.peptide.persistence.SqlStorage
|
||||
import io.ktor.client.plugins.websocket.ws
|
||||
import io.ktor.websocket.CloseReason
|
||||
import io.ktor.websocket.Frame
|
||||
|
|
@ -69,7 +69,7 @@ object RealtimeSocket {
|
|||
var socket: WebSocketSession? = null
|
||||
|
||||
private val channelRegistrator: ChannelRegistrator
|
||||
get() = ChannelRegistrator(RevoltApplication.instance)
|
||||
get() = ChannelRegistrator(PeptideApplication.instance)
|
||||
|
||||
private var _disconnectionState = mutableStateOf(DisconnectionState.Reconnecting)
|
||||
val disconnectionState: DisconnectionState
|
||||
|
|
@ -87,7 +87,7 @@ object RealtimeSocket {
|
|||
|
||||
socket?.close(CloseReason(CloseReason.Codes.NORMAL, "Reconnecting to websocket."))
|
||||
|
||||
RevoltHttp.ws(RevoltAPI.getCurrentWebSocketUrl()) {
|
||||
PeptideHttp.ws(PeptideAPI.getCurrentWebSocketUrl()) {
|
||||
socket = this
|
||||
|
||||
Log.d("RealtimeSocket", "Connected to websocket.")
|
||||
|
|
@ -97,7 +97,7 @@ object RealtimeSocket {
|
|||
// Send authorization frame
|
||||
val authFrame = AuthorizationFrame("Authenticate", token)
|
||||
val authFrameString =
|
||||
RevoltJson.encodeToString(AuthorizationFrame.serializer(), authFrame)
|
||||
PeptideJson.encodeToString(AuthorizationFrame.serializer(), authFrame)
|
||||
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -108,13 +108,13 @@ object RealtimeSocket {
|
|||
)
|
||||
}"
|
||||
)
|
||||
send(RevoltJson.encodeToString(AuthorizationFrame.serializer(), authFrame))
|
||||
send(PeptideJson.encodeToString(AuthorizationFrame.serializer(), authFrame))
|
||||
|
||||
incoming.consumeEach { frame ->
|
||||
if (frame is Frame.Text) {
|
||||
val frameString = frame.readText()
|
||||
val frameType =
|
||||
RevoltJson.decodeFromString(AnyFrame.serializer(), frameString).type
|
||||
PeptideJson.decodeFromString(AnyFrame.serializer(), frameString).type
|
||||
|
||||
handleFrame(frameType, frameString)
|
||||
}
|
||||
|
|
@ -126,29 +126,29 @@ object RealtimeSocket {
|
|||
if (disconnectionState != DisconnectionState.Connected) return
|
||||
|
||||
val pingPacket = PingFrame("Ping", System.currentTimeMillis())
|
||||
socket?.send(RevoltJson.encodeToString(PingFrame.serializer(), pingPacket))
|
||||
socket?.send(PeptideJson.encodeToString(PingFrame.serializer(), pingPacket))
|
||||
Log.d("RealtimeSocket", "Sent ping frame with ${pingPacket.data}")
|
||||
}
|
||||
|
||||
private suspend fun handleFrame(type: String, rawFrame: String) {
|
||||
when (type) {
|
||||
"Pong" -> {
|
||||
val pongFrame = RevoltJson.decodeFromString(PongFrame.serializer(), rawFrame)
|
||||
val pongFrame = PeptideJson.decodeFromString(PongFrame.serializer(), rawFrame)
|
||||
Log.d("RealtimeSocket", "Received pong frame for ${pongFrame.data}")
|
||||
}
|
||||
|
||||
"Bulk" -> {
|
||||
val bulkFrame = RevoltJson.decodeFromString(BulkFrame.serializer(), rawFrame)
|
||||
val bulkFrame = PeptideJson.decodeFromString(BulkFrame.serializer(), rawFrame)
|
||||
Log.d("RealtimeSocket", "Received bulk frame with ${bulkFrame.v.size} sub-frames.")
|
||||
bulkFrame.v.forEach { subFrame ->
|
||||
val subFrameType =
|
||||
RevoltJson.decodeFromString(AnyFrame.serializer(), subFrame.toString()).type
|
||||
PeptideJson.decodeFromString(AnyFrame.serializer(), subFrame.toString()).type
|
||||
handleFrame(subFrameType, subFrame.toString())
|
||||
}
|
||||
}
|
||||
|
||||
"Ready" -> {
|
||||
val readyFrame = RevoltJson.decodeFromString(ReadyFrame.serializer(), rawFrame)
|
||||
val readyFrame = PeptideJson.decodeFromString(ReadyFrame.serializer(), rawFrame)
|
||||
|
||||
logcat {
|
||||
"Received ready frame with ${readyFrame.users.size} users, " +
|
||||
|
|
@ -160,11 +160,11 @@ object RealtimeSocket {
|
|||
|
||||
Log.d("RealtimeSocket", "Adding users to cache.")
|
||||
val userMap = readyFrame.users.associateBy { it.id!! }
|
||||
RevoltAPI.userCache.putAll(userMap)
|
||||
PeptideAPI.userCache.putAll(userMap)
|
||||
|
||||
Log.d("RealtimeSocket", "Adding servers to cache.")
|
||||
val serverMap = readyFrame.servers.associateBy { it.id!! }
|
||||
RevoltAPI.serverCache.putAll(serverMap)
|
||||
PeptideAPI.serverCache.putAll(serverMap)
|
||||
|
||||
// Cache servers in persistent local database
|
||||
readyFrame.servers.map {
|
||||
|
|
@ -195,12 +195,12 @@ object RealtimeSocket {
|
|||
"Deleted server $it from local database due to not being in ready frame."
|
||||
)
|
||||
// Conversely, remove the server from the API state
|
||||
RevoltAPI.serverCache.remove(it)
|
||||
PeptideAPI.serverCache.remove(it)
|
||||
}
|
||||
|
||||
Log.d("RealtimeSocket", "Adding channels to cache.")
|
||||
val channelMap = readyFrame.channels.associateBy { it.id!! }
|
||||
RevoltAPI.channelCache.putAll(channelMap)
|
||||
PeptideAPI.channelCache.putAll(channelMap)
|
||||
|
||||
// Cache channels in persistent local database
|
||||
readyFrame.channels.map {
|
||||
|
|
@ -215,7 +215,7 @@ object RealtimeSocket {
|
|||
it.name,
|
||||
it.owner,
|
||||
it.description,
|
||||
if (it.channelType == ChannelType.DirectMessage) it.recipients?.firstOrNull { u -> u != RevoltAPI.selfId } else null,
|
||||
if (it.channelType == ChannelType.DirectMessage) it.recipients?.firstOrNull { u -> u != PeptideAPI.selfId } else null,
|
||||
it.icon?.id,
|
||||
it.lastMessageID,
|
||||
if (it.active == true) 1L else 0L,
|
||||
|
|
@ -236,21 +236,21 @@ object RealtimeSocket {
|
|||
"Deleted channel $it from local database due to not being in ready frame."
|
||||
)
|
||||
// Conversely, remove the channel from the API state
|
||||
RevoltAPI.channelCache.remove(it)
|
||||
PeptideAPI.channelCache.remove(it)
|
||||
}
|
||||
|
||||
Log.d("RealtimeSocket", "Adding emojis to cache.")
|
||||
val emojiMap = readyFrame.emojis.associateBy { it.id!! }
|
||||
RevoltAPI.emojiCache.putAll(emojiMap)
|
||||
PeptideAPI.emojiCache.putAll(emojiMap)
|
||||
|
||||
Log.d("RealtimeSocket", "Registering push notification channels.")
|
||||
channelRegistrator.register()
|
||||
|
||||
RevoltAPI.closeHydration()
|
||||
PeptideAPI.closeHydration()
|
||||
}
|
||||
|
||||
"Message" -> {
|
||||
val messageFrame = RevoltJson.decodeFromString(MessageFrame.serializer(), rawFrame)
|
||||
val messageFrame = PeptideJson.decodeFromString(MessageFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received message frame for ${messageFrame.id} in channel ${messageFrame.channel}."
|
||||
|
|
@ -261,30 +261,30 @@ object RealtimeSocket {
|
|||
return
|
||||
}
|
||||
|
||||
RevoltAPI.messageCache[messageFrame.id] = messageFrame
|
||||
PeptideAPI.messageCache[messageFrame.id] = messageFrame
|
||||
|
||||
messageFrame.channel?.let {
|
||||
if (RevoltAPI.channelCache[it] == null) {
|
||||
if (PeptideAPI.channelCache[it] == null) {
|
||||
Log.d("RealtimeSocket", "Channel $it not found in cache. Ignoring.")
|
||||
return
|
||||
}
|
||||
|
||||
RevoltAPI.channelCache[it] =
|
||||
RevoltAPI.channelCache[it]!!.copy(lastMessageID = messageFrame.id)
|
||||
PeptideAPI.channelCache[it] =
|
||||
PeptideAPI.channelCache[it]!!.copy(lastMessageID = messageFrame.id)
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(messageFrame)
|
||||
PeptideAPI.wsFrameChannel.send(messageFrame)
|
||||
}
|
||||
}
|
||||
|
||||
"MessageAppend" -> {
|
||||
val messageAppendFrame =
|
||||
RevoltJson.decodeFromString(MessageAppendFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(MessageAppendFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received message append frame for ${messageAppendFrame.id} in channel ${messageAppendFrame.channel}."
|
||||
)
|
||||
|
||||
var message = RevoltAPI.messageCache[messageAppendFrame.id]
|
||||
var message = PeptideAPI.messageCache[messageAppendFrame.id]
|
||||
|
||||
if (message == null) {
|
||||
Log.d(
|
||||
|
|
@ -298,20 +298,20 @@ object RealtimeSocket {
|
|||
message = message!!.copy(embeds = message!!.embeds?.plus(it) ?: it)
|
||||
}
|
||||
|
||||
RevoltAPI.messageCache[messageAppendFrame.id] = message!!
|
||||
PeptideAPI.messageCache[messageAppendFrame.id] = message!!
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(messageAppendFrame)
|
||||
PeptideAPI.wsFrameChannel.send(messageAppendFrame)
|
||||
}
|
||||
|
||||
"MessageUpdate" -> {
|
||||
val messageUpdateFrame =
|
||||
RevoltJson.decodeFromString(MessageUpdateFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(MessageUpdateFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received message update frame for ${messageUpdateFrame.id} in channel ${messageUpdateFrame.channel}."
|
||||
)
|
||||
|
||||
val oldMessage = RevoltAPI.messageCache[messageUpdateFrame.id]
|
||||
val oldMessage = PeptideAPI.messageCache[messageUpdateFrame.id]
|
||||
if (oldMessage == null) {
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -323,7 +323,7 @@ object RealtimeSocket {
|
|||
val rawMessage: MessageFrame
|
||||
try {
|
||||
rawMessage =
|
||||
RevoltJson.decodeFromJsonElement(
|
||||
PeptideJson.decodeFromJsonElement(
|
||||
MessageFrame.serializer(),
|
||||
messageUpdateFrame.data
|
||||
)
|
||||
|
|
@ -337,28 +337,28 @@ object RealtimeSocket {
|
|||
"Merging message ${messageUpdateFrame.id} with updated partial."
|
||||
)
|
||||
|
||||
RevoltAPI.messageCache[messageUpdateFrame.id] =
|
||||
PeptideAPI.messageCache[messageUpdateFrame.id] =
|
||||
oldMessage.mergeWithPartial(rawMessage)
|
||||
|
||||
messageUpdateFrame.channel.let {
|
||||
if (RevoltAPI.channelCache[it] == null) {
|
||||
if (PeptideAPI.channelCache[it] == null) {
|
||||
Log.d("RealtimeSocket", "Channel $it not found in cache. Ignoring.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(messageUpdateFrame)
|
||||
PeptideAPI.wsFrameChannel.send(messageUpdateFrame)
|
||||
}
|
||||
|
||||
"MessageDelete" -> {
|
||||
val messageDeleteFrame =
|
||||
RevoltJson.decodeFromString(MessageDeleteFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(MessageDeleteFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received message react frame for ${messageDeleteFrame.id}."
|
||||
)
|
||||
|
||||
val message = RevoltAPI.messageCache[messageDeleteFrame.id]
|
||||
val message = PeptideAPI.messageCache[messageDeleteFrame.id]
|
||||
if (message == null) {
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -367,19 +367,19 @@ object RealtimeSocket {
|
|||
return
|
||||
}
|
||||
|
||||
RevoltAPI.messageCache.remove(messageDeleteFrame.id)
|
||||
RevoltAPI.wsFrameChannel.send(messageDeleteFrame)
|
||||
PeptideAPI.messageCache.remove(messageDeleteFrame.id)
|
||||
PeptideAPI.wsFrameChannel.send(messageDeleteFrame)
|
||||
}
|
||||
|
||||
"MessageReact" -> {
|
||||
val messageReactFrame =
|
||||
RevoltJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received message react frame for ${messageReactFrame.id}."
|
||||
)
|
||||
|
||||
val oldMessage = RevoltAPI.messageCache[messageReactFrame.id]
|
||||
val oldMessage = PeptideAPI.messageCache[messageReactFrame.id]
|
||||
if (oldMessage == null) {
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -394,21 +394,21 @@ object RealtimeSocket {
|
|||
forEmoji.add(messageReactFrame.user_id)
|
||||
reactions[messageReactFrame.emoji_id] = forEmoji
|
||||
|
||||
RevoltAPI.messageCache[messageReactFrame.id] =
|
||||
PeptideAPI.messageCache[messageReactFrame.id] =
|
||||
oldMessage.copy(reactions = reactions)
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(messageReactFrame)
|
||||
PeptideAPI.wsFrameChannel.send(messageReactFrame)
|
||||
}
|
||||
|
||||
"MessageUnreact" -> {
|
||||
val messageUnreactFrame =
|
||||
RevoltJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(MessageReactFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received message unreact frame for ${messageUnreactFrame.id}."
|
||||
)
|
||||
|
||||
val oldMessage = RevoltAPI.messageCache[messageUnreactFrame.id]
|
||||
val oldMessage = PeptideAPI.messageCache[messageUnreactFrame.id]
|
||||
if (oldMessage == null) {
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -428,38 +428,38 @@ object RealtimeSocket {
|
|||
reactions[messageUnreactFrame.emoji_id] = forEmoji
|
||||
}
|
||||
|
||||
RevoltAPI.messageCache[messageUnreactFrame.id] =
|
||||
PeptideAPI.messageCache[messageUnreactFrame.id] =
|
||||
oldMessage.copy(reactions = reactions)
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(messageUnreactFrame)
|
||||
PeptideAPI.wsFrameChannel.send(messageUnreactFrame)
|
||||
}
|
||||
|
||||
"UserUpdate" -> {
|
||||
val userUpdateFrame =
|
||||
RevoltJson.decodeFromString(UserUpdateFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(UserUpdateFrame.serializer(), rawFrame)
|
||||
|
||||
val existing = RevoltAPI.userCache[userUpdateFrame.id]
|
||||
val existing = PeptideAPI.userCache[userUpdateFrame.id]
|
||||
?: return // if we don't have the user no point in updating it
|
||||
|
||||
if (userUpdateFrame.clear != null) {
|
||||
if (userUpdateFrame.clear.contains("Avatar")) {
|
||||
RevoltAPI.userCache[userUpdateFrame.id] =
|
||||
PeptideAPI.userCache[userUpdateFrame.id] =
|
||||
existing.copy(avatar = null)
|
||||
}
|
||||
}
|
||||
|
||||
RevoltAPI.userCache[userUpdateFrame.id] =
|
||||
PeptideAPI.userCache[userUpdateFrame.id] =
|
||||
existing.mergeWithPartial(userUpdateFrame.data)
|
||||
}
|
||||
|
||||
"UserRelationship" -> {
|
||||
val userRelationshipFrame =
|
||||
RevoltJson.decodeFromString(UserRelationshipFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(UserRelationshipFrame.serializer(), rawFrame)
|
||||
|
||||
val existing = RevoltAPI.userCache[userRelationshipFrame.user.id]
|
||||
val existing = PeptideAPI.userCache[userRelationshipFrame.user.id]
|
||||
|
||||
if (existing == null && userRelationshipFrame.user.id != null) {
|
||||
RevoltAPI.userCache[userRelationshipFrame.user.id] =
|
||||
PeptideAPI.userCache[userRelationshipFrame.user.id] =
|
||||
userRelationshipFrame.user.copy(
|
||||
relationship = userRelationshipFrame.status ?: "None"
|
||||
)
|
||||
|
|
@ -467,7 +467,7 @@ object RealtimeSocket {
|
|||
val merged = existing.mergeWithPartial(userRelationshipFrame.user).copy(
|
||||
relationship = userRelationshipFrame.status ?: "None"
|
||||
)
|
||||
RevoltAPI.userCache[userRelationshipFrame.user.id] = merged
|
||||
PeptideAPI.userCache[userRelationshipFrame.user.id] = merged
|
||||
} else {
|
||||
Log.w("RealtimeSocket", "Invalid UserRelationship frame: $rawFrame")
|
||||
}
|
||||
|
|
@ -475,13 +475,13 @@ object RealtimeSocket {
|
|||
|
||||
"ChannelUpdate" -> {
|
||||
val channelUpdateFrame =
|
||||
RevoltJson.decodeFromString(ChannelUpdateFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ChannelUpdateFrame.serializer(), rawFrame)
|
||||
|
||||
val existing = RevoltAPI.channelCache[channelUpdateFrame.id]
|
||||
val existing = PeptideAPI.channelCache[channelUpdateFrame.id]
|
||||
?: return // if we don't have the channel no point in updating it
|
||||
|
||||
val combined = existing.mergeWithPartial(channelUpdateFrame.data)
|
||||
RevoltAPI.channelCache[channelUpdateFrame.id] = combined
|
||||
PeptideAPI.channelCache[channelUpdateFrame.id] = combined
|
||||
|
||||
database.channelQueries.upsert(
|
||||
channelUpdateFrame.id,
|
||||
|
|
@ -490,7 +490,7 @@ object RealtimeSocket {
|
|||
combined.name,
|
||||
combined.owner,
|
||||
combined.description,
|
||||
if (combined.channelType == ChannelType.DirectMessage) combined.recipients?.firstOrNull { u -> u != RevoltAPI.selfId } else null,
|
||||
if (combined.channelType == ChannelType.DirectMessage) combined.recipients?.firstOrNull { u -> u != PeptideAPI.selfId } else null,
|
||||
combined.icon?.id,
|
||||
combined.lastMessageID,
|
||||
if (combined.active == true) 1L else 0L,
|
||||
|
|
@ -501,14 +501,14 @@ object RealtimeSocket {
|
|||
|
||||
"ChannelCreate" -> {
|
||||
val channelCreateFrame =
|
||||
RevoltJson.decodeFromString(Channel.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(Channel.serializer(), rawFrame)
|
||||
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received channel create frame for ${channelCreateFrame.id}, with name ${channelCreateFrame.name}. Adding to cache."
|
||||
)
|
||||
|
||||
RevoltAPI.channelCache[channelCreateFrame.id!!] = channelCreateFrame
|
||||
PeptideAPI.channelCache[channelCreateFrame.id!!] = channelCreateFrame
|
||||
database.channelQueries.upsert(
|
||||
channelCreateFrame.id,
|
||||
channelCreateFrame.channelType?.value ?: ChannelType.TextChannel.value,
|
||||
|
|
@ -516,7 +516,7 @@ object RealtimeSocket {
|
|||
channelCreateFrame.name,
|
||||
channelCreateFrame.owner,
|
||||
channelCreateFrame.description,
|
||||
if (channelCreateFrame.channelType == ChannelType.DirectMessage) channelCreateFrame.recipients?.firstOrNull { u -> u != RevoltAPI.selfId } else null,
|
||||
if (channelCreateFrame.channelType == ChannelType.DirectMessage) channelCreateFrame.recipients?.firstOrNull { u -> u != PeptideAPI.selfId } else null,
|
||||
channelCreateFrame.icon?.id,
|
||||
channelCreateFrame.lastMessageID,
|
||||
if (channelCreateFrame.active == true) 1L else 0L,
|
||||
|
|
@ -527,13 +527,13 @@ object RealtimeSocket {
|
|||
|
||||
"ChannelDelete" -> {
|
||||
val channelDeleteFrame =
|
||||
RevoltJson.decodeFromString(ChannelDeleteFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ChannelDeleteFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received channel delete frame for ${channelDeleteFrame.id}. Removing from cache."
|
||||
)
|
||||
|
||||
val currentChannel = RevoltAPI.channelCache[channelDeleteFrame.id]
|
||||
val currentChannel = PeptideAPI.channelCache[channelDeleteFrame.id]
|
||||
if (currentChannel == null) {
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -542,11 +542,11 @@ object RealtimeSocket {
|
|||
return
|
||||
}
|
||||
|
||||
RevoltAPI.channelCache.remove(channelDeleteFrame.id)
|
||||
PeptideAPI.channelCache.remove(channelDeleteFrame.id)
|
||||
database.channelQueries.delete(channelDeleteFrame.id)
|
||||
|
||||
if (currentChannel.server != null) {
|
||||
val existingServer = RevoltAPI.serverCache[currentChannel.server]
|
||||
val existingServer = PeptideAPI.serverCache[currentChannel.server]
|
||||
|
||||
if (existingServer == null) {
|
||||
Log.d(
|
||||
|
|
@ -556,39 +556,39 @@ object RealtimeSocket {
|
|||
return
|
||||
}
|
||||
|
||||
RevoltAPI.serverCache[currentChannel.server] = existingServer.copy(
|
||||
PeptideAPI.serverCache[currentChannel.server] = existingServer.copy(
|
||||
channels = existingServer.channels?.filter { it != channelDeleteFrame.id }
|
||||
?: emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(channelDeleteFrame)
|
||||
PeptideAPI.wsFrameChannel.send(channelDeleteFrame)
|
||||
}
|
||||
|
||||
"ChannelAck" -> {
|
||||
val channelAckFrame =
|
||||
RevoltJson.decodeFromString(ChannelAckFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ChannelAckFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received channel ack frame for ${channelAckFrame.id} with new newest ${channelAckFrame.messageId}."
|
||||
)
|
||||
|
||||
RevoltAPI.unreads.processExternalAck(channelAckFrame.id, channelAckFrame.messageId)
|
||||
PeptideAPI.unreads.processExternalAck(channelAckFrame.id, channelAckFrame.messageId)
|
||||
}
|
||||
|
||||
"ServerCreate" -> {
|
||||
val serverCreateFrame =
|
||||
RevoltJson.decodeFromString(ServerCreateFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerCreateFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server create frame for ${serverCreateFrame.id}, with name ${serverCreateFrame.server.name}. Adding to cache."
|
||||
)
|
||||
|
||||
RevoltAPI.serverCache[serverCreateFrame.id] = serverCreateFrame.server
|
||||
PeptideAPI.serverCache[serverCreateFrame.id] = serverCreateFrame.server
|
||||
|
||||
serverCreateFrame.channels.forEach { channel ->
|
||||
if (channel.id == null) return@forEach
|
||||
RevoltAPI.channelCache[channel.id] = channel
|
||||
PeptideAPI.channelCache[channel.id] = channel
|
||||
}
|
||||
|
||||
if (serverCreateFrame.server.owner != null && serverCreateFrame.server.name != null) {
|
||||
|
|
@ -606,35 +606,35 @@ object RealtimeSocket {
|
|||
|
||||
"ChannelStartTyping" -> {
|
||||
val channelStartTypingFrame =
|
||||
RevoltJson.decodeFromString(ChannelStartTypingFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ChannelStartTypingFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received channel start typing frame for ${channelStartTypingFrame.id}."
|
||||
)
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(channelStartTypingFrame)
|
||||
PeptideAPI.wsFrameChannel.send(channelStartTypingFrame)
|
||||
}
|
||||
|
||||
"ChannelStopTyping" -> {
|
||||
val channelStopTypingFrame =
|
||||
RevoltJson.decodeFromString(ChannelStopTypingFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ChannelStopTypingFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received channel stop typing frame for ${channelStopTypingFrame.id}."
|
||||
)
|
||||
|
||||
RevoltAPI.wsFrameChannel.send(channelStopTypingFrame)
|
||||
PeptideAPI.wsFrameChannel.send(channelStopTypingFrame)
|
||||
}
|
||||
|
||||
"ServerUpdate" -> {
|
||||
val serverUpdateFrame =
|
||||
RevoltJson.decodeFromString(ServerUpdateFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerUpdateFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server update frame for ${serverUpdateFrame.id}."
|
||||
)
|
||||
|
||||
val existing = RevoltAPI.serverCache[serverUpdateFrame.id]
|
||||
val existing = PeptideAPI.serverCache[serverUpdateFrame.id]
|
||||
?: return // if we don't have the server no point in updating it
|
||||
|
||||
var updated =
|
||||
|
|
@ -649,7 +649,7 @@ object RealtimeSocket {
|
|||
}
|
||||
}
|
||||
|
||||
RevoltAPI.serverCache[serverUpdateFrame.id] = updated
|
||||
PeptideAPI.serverCache[serverUpdateFrame.id] = updated
|
||||
|
||||
if (updated.id != null && updated.owner != null && updated.name != null) {
|
||||
try {
|
||||
|
|
@ -670,25 +670,25 @@ object RealtimeSocket {
|
|||
|
||||
"ServerDelete" -> {
|
||||
val serverDeleteFrame =
|
||||
RevoltJson.decodeFromString(ServerDeleteFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerDeleteFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server delete frame for ${serverDeleteFrame.id}."
|
||||
)
|
||||
|
||||
RevoltAPI.serverCache.remove(serverDeleteFrame.id)
|
||||
PeptideAPI.serverCache.remove(serverDeleteFrame.id)
|
||||
database.serverQueries.delete(serverDeleteFrame.id)
|
||||
}
|
||||
|
||||
"ServerMemberUpdate" -> {
|
||||
val serverMemberUpdateFrame =
|
||||
RevoltJson.decodeFromString(ServerMemberUpdateFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerMemberUpdateFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server member update frame for ${serverMemberUpdateFrame.id.user} in ${serverMemberUpdateFrame.id.server}."
|
||||
)
|
||||
|
||||
val existing = RevoltAPI.members.getMember(
|
||||
val existing = PeptideAPI.members.getMember(
|
||||
serverMemberUpdateFrame.id.server,
|
||||
serverMemberUpdateFrame.id.user
|
||||
)
|
||||
|
|
@ -706,12 +706,12 @@ object RealtimeSocket {
|
|||
|
||||
Log.d("RealtimeSocket", "Updated member: $updated")
|
||||
|
||||
RevoltAPI.members.setMember(serverMemberUpdateFrame.id.server, updated)
|
||||
PeptideAPI.members.setMember(serverMemberUpdateFrame.id.server, updated)
|
||||
}
|
||||
|
||||
"ServerMemberJoin" -> {
|
||||
val serverMemberJoinFrame =
|
||||
RevoltJson.decodeFromString(ServerMemberJoinFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerMemberJoinFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server member join frame for ${serverMemberJoinFrame.user} in ${serverMemberJoinFrame.id}."
|
||||
|
|
@ -719,18 +719,18 @@ object RealtimeSocket {
|
|||
|
||||
val member = fetchMember(serverMemberJoinFrame.id, serverMemberJoinFrame.user)
|
||||
|
||||
RevoltAPI.members.setMember(serverMemberJoinFrame.id, member)
|
||||
PeptideAPI.members.setMember(serverMemberJoinFrame.id, member)
|
||||
}
|
||||
|
||||
"ServerMemberLeave" -> {
|
||||
val serverMemberLeaveFrame =
|
||||
RevoltJson.decodeFromString(ServerMemberLeaveFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerMemberLeaveFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server member leave frame for ${serverMemberLeaveFrame.user} in ${serverMemberLeaveFrame.id}."
|
||||
)
|
||||
|
||||
RevoltAPI.members.removeMember(
|
||||
PeptideAPI.members.removeMember(
|
||||
serverMemberLeaveFrame.id,
|
||||
serverMemberLeaveFrame.user
|
||||
)
|
||||
|
|
@ -738,13 +738,13 @@ object RealtimeSocket {
|
|||
|
||||
"ServerRoleUpdate" -> {
|
||||
val serverRoleUpdateFrame =
|
||||
RevoltJson.decodeFromString(ServerRoleUpdateFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerRoleUpdateFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server role update frame for ${serverRoleUpdateFrame.id}."
|
||||
)
|
||||
|
||||
val server = RevoltAPI.serverCache[serverRoleUpdateFrame.id]
|
||||
val server = PeptideAPI.serverCache[serverRoleUpdateFrame.id]
|
||||
if (server == null) {
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -766,7 +766,7 @@ object RealtimeSocket {
|
|||
Pair(serverRoleUpdateFrame.roleId, newRole)
|
||||
) ?: mapOf(serverRoleUpdateFrame.roleId to newRole)
|
||||
)
|
||||
RevoltAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
||||
PeptideAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
||||
} else {
|
||||
// True role update.
|
||||
Log.d(
|
||||
|
|
@ -779,19 +779,19 @@ object RealtimeSocket {
|
|||
Pair(serverRoleUpdateFrame.roleId, updatedRole)
|
||||
)
|
||||
)
|
||||
RevoltAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
||||
PeptideAPI.serverCache[serverRoleUpdateFrame.id] = newServer
|
||||
}
|
||||
}
|
||||
|
||||
"ServerRoleDelete" -> {
|
||||
val serverRoleDeleteFrame =
|
||||
RevoltJson.decodeFromString(ServerRoleDeleteFrame.serializer(), rawFrame)
|
||||
PeptideJson.decodeFromString(ServerRoleDeleteFrame.serializer(), rawFrame)
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
"Received server role delete frame for ${serverRoleDeleteFrame.id} and role ${serverRoleDeleteFrame.roleId}."
|
||||
)
|
||||
|
||||
val server = RevoltAPI.serverCache[serverRoleDeleteFrame.id]
|
||||
val server = PeptideAPI.serverCache[serverRoleDeleteFrame.id]
|
||||
if (server == null) {
|
||||
Log.d(
|
||||
"RealtimeSocket",
|
||||
|
|
@ -803,7 +803,7 @@ object RealtimeSocket {
|
|||
val newRoles = server.roles?.toMutableMap() ?: mutableMapOf()
|
||||
newRoles.remove(serverRoleDeleteFrame.roleId)
|
||||
|
||||
RevoltAPI.serverCache[serverRoleDeleteFrame.id] =
|
||||
PeptideAPI.serverCache[serverRoleDeleteFrame.id] =
|
||||
server.copy(roles = newRoles)
|
||||
}
|
||||
|
||||
|
|
@ -819,7 +819,7 @@ object RealtimeSocket {
|
|||
}
|
||||
|
||||
private suspend fun pushReconnectEvent() {
|
||||
RevoltAPI.wsFrameChannel.send(RealtimeSocketFrames.Reconnected)
|
||||
PeptideAPI.wsFrameChannel.send(RealtimeSocketFrames.Reconnected)
|
||||
}
|
||||
|
||||
suspend fun beginTyping(channelId: String) {
|
||||
|
|
@ -827,7 +827,7 @@ object RealtimeSocket {
|
|||
|
||||
val beginTypingFrame = BeginTypingFrame("BeginTyping", channelId)
|
||||
socket?.send(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
BeginTypingFrame.serializer(),
|
||||
beginTypingFrame
|
||||
)
|
||||
|
|
@ -839,7 +839,7 @@ object RealtimeSocket {
|
|||
|
||||
val endTypingFrame = EndTypingFrame("EndTyping", channelId)
|
||||
socket?.send(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
EndTypingFrame.serializer(),
|
||||
endTypingFrame
|
||||
)
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
package chat.revolt.api.realtime.frames.receivable
|
||||
package chat.peptide.api.realtime.frames.receivable
|
||||
|
||||
import chat.revolt.api.schemas.Channel
|
||||
import chat.revolt.api.schemas.ChannelVoiceState
|
||||
import chat.revolt.api.schemas.Embed
|
||||
import chat.revolt.api.schemas.Emoji
|
||||
import chat.revolt.api.schemas.Member
|
||||
import chat.revolt.api.schemas.Message
|
||||
import chat.revolt.api.schemas.Role
|
||||
import chat.revolt.api.schemas.Server
|
||||
import chat.revolt.api.schemas.ServerUserChoice
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import chat.peptide.api.schemas.ChannelVoiceState
|
||||
import chat.peptide.api.schemas.Embed
|
||||
import chat.peptide.api.schemas.Emoji
|
||||
import chat.peptide.api.schemas.Member
|
||||
import chat.peptide.api.schemas.Message
|
||||
import chat.peptide.api.schemas.Role
|
||||
import chat.peptide.api.schemas.Server
|
||||
import chat.peptide.api.schemas.ServerUserChoice
|
||||
import chat.peptide.api.schemas.User
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.realtime.frames.sendable
|
||||
package chat.peptide.api.realtime.frames.sendable
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package chat.revolt.api.routes.account
|
||||
package chat.peptide.api.routes.account
|
||||
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
|
|
@ -104,22 +104,22 @@ data class EmailPasswordAssessment(
|
|||
val proceedMfa: Boolean = false,
|
||||
val mfaSpec: MfaLoginSpec? = null,
|
||||
val firstUserHints: UserHints? = null,
|
||||
val error: RevoltError? = null
|
||||
val error: PeptideError? = null
|
||||
)
|
||||
|
||||
suspend fun negotiateAuthentication(email: String, password: String): EmailPasswordAssessment {
|
||||
val sessionName = friendlySessionName()
|
||||
|
||||
val response: HttpResponse = RevoltHttp.post("/auth/session/login".api()) {
|
||||
val response: HttpResponse = PeptideHttp.post("/auth/session/login".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(LoginNegotiation(email, password, sessionName, null))
|
||||
}
|
||||
|
||||
val responseContent = response.bodyAsText()
|
||||
Log.d("Revolt", "negotiateAuthentication: $responseContent")
|
||||
Log.d("Peptide", "negotiateAuthentication: $responseContent")
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), responseContent)
|
||||
return EmailPasswordAssessment(error = error)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -127,22 +127,22 @@ suspend fun negotiateAuthentication(email: String, password: String): EmailPassw
|
|||
|
||||
if (response.status == HttpStatusCode.InternalServerError) {
|
||||
return EmailPasswordAssessment(
|
||||
error = RevoltError(
|
||||
error = PeptideError(
|
||||
"InternalServerError"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val responseJson = RevoltJson.decodeFromString(MfaCheck.serializer(), responseContent)
|
||||
val responseJson = PeptideJson.decodeFromString(MfaCheck.serializer(), responseContent)
|
||||
|
||||
return when (responseJson.result) {
|
||||
"Success" -> EmailPasswordAssessment(
|
||||
firstUserHints = RevoltJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||
firstUserHints = PeptideJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||
)
|
||||
|
||||
"MFA" -> EmailPasswordAssessment(
|
||||
proceedMfa = true,
|
||||
mfaSpec = RevoltJson.decodeFromString(MfaLoginSpec.serializer(), responseContent)
|
||||
mfaSpec = PeptideJson.decodeFromString(MfaLoginSpec.serializer(), responseContent)
|
||||
)
|
||||
|
||||
else -> throw Exception("Unknown result: ${responseJson.result}")
|
||||
|
|
@ -153,23 +153,23 @@ suspend fun authenticateWithMfaTotpCode(
|
|||
mfaTicket: String,
|
||||
mfaResponse: MfaResponseTotpCode
|
||||
): EmailPasswordAssessment {
|
||||
val response: HttpResponse = RevoltHttp.post("/auth/session/login".api()) {
|
||||
val response: HttpResponse = PeptideHttp.post("/auth/session/login".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(LoginMfaAmendmentTotpCode(mfaTicket, mfaResponse, friendlySessionName()))
|
||||
}
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response.bodyAsText())
|
||||
return EmailPasswordAssessment(error = error)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val responseContent = response.bodyAsText()
|
||||
Log.d("Revolt", "authenticateWithMfaTotpCode: $responseContent")
|
||||
Log.d("Peptide", "authenticateWithMfaTotpCode: $responseContent")
|
||||
|
||||
return EmailPasswordAssessment(
|
||||
firstUserHints = RevoltJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||
firstUserHints = PeptideJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -177,26 +177,26 @@ suspend fun authenticateWithMfaRecoveryCode(
|
|||
mfaTicket: String,
|
||||
mfaResponse: MfaResponseRecoveryCode
|
||||
): EmailPasswordAssessment {
|
||||
val response: HttpResponse = RevoltHttp.post("/auth/session/login".api()) {
|
||||
val response: HttpResponse = PeptideHttp.post("/auth/session/login".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(LoginMfaAmendmentRecoveryCode(mfaTicket, mfaResponse, friendlySessionName()))
|
||||
}
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response.bodyAsText())
|
||||
return EmailPasswordAssessment(error = error)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val responseContent = response.bodyAsText()
|
||||
Log.d("Revolt", "authenticateWithMfaRecoveryCode: $responseContent")
|
||||
Log.d("Peptide", "authenticateWithMfaRecoveryCode: $responseContent")
|
||||
|
||||
return EmailPasswordAssessment(
|
||||
firstUserHints = RevoltJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||
firstUserHints = PeptideJson.decodeFromString(UserHints.serializer(), responseContent)
|
||||
)
|
||||
}
|
||||
|
||||
fun friendlySessionName(): String {
|
||||
return "Revolt Android on ${Build.MANUFACTURER} ${Build.MODEL}"
|
||||
return "Peptide Android on ${Build.MANUFACTURER} ${Build.MODEL}"
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package chat.revolt.api.routes.account
|
||||
package chat.peptide.api.routes.account
|
||||
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.schemas.RsResult
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.schemas.RsResult
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
|
|
@ -21,8 +21,8 @@ data class RegistrationBody(
|
|||
val captcha: String
|
||||
)
|
||||
|
||||
suspend fun register(body: RegistrationBody): RsResult<Unit, RevoltError> {
|
||||
val response = RevoltHttp.post("/auth/account/create".api()) {
|
||||
suspend fun register(body: RegistrationBody): RsResult<Unit, PeptideError> {
|
||||
val response = PeptideHttp.post("/auth/account/create".api()) {
|
||||
setBody(body)
|
||||
contentType(ContentType.Application.Json)
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ suspend fun register(body: RegistrationBody): RsResult<Unit, RevoltError> {
|
|||
val responseContent = response.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), responseContent)
|
||||
return RsResult.err(error)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package chat.revolt.api.routes.auth
|
||||
package chat.peptide.api.routes.auth
|
||||
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.schemas.Session
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.Session
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
|
|
@ -11,21 +11,21 @@ import io.ktor.client.statement.bodyAsText
|
|||
import kotlinx.serialization.builtins.ListSerializer
|
||||
|
||||
suspend fun fetchAllSessions(): List<Session> {
|
||||
val response = RevoltHttp.get("/auth/session/all".api())
|
||||
val response = PeptideHttp.get("/auth/session/all".api())
|
||||
.bodyAsText()
|
||||
|
||||
return RevoltJson.decodeFromString(
|
||||
return PeptideJson.decodeFromString(
|
||||
ListSerializer(Session.serializer()),
|
||||
response
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun logoutSessionById(id: String) {
|
||||
RevoltHttp.delete("/auth/session/$id".api())
|
||||
PeptideHttp.delete("/auth/session/$id".api())
|
||||
}
|
||||
|
||||
suspend fun logoutAllSessions(includingSelf: Boolean = false) {
|
||||
RevoltHttp.delete("/auth/session/all".api()) {
|
||||
PeptideHttp.delete("/auth/session/all".api()) {
|
||||
parameter("revoke_self", includingSelf)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
package chat.revolt.api.routes.channel
|
||||
package chat.peptide.api.routes.channel
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.internals.ULID
|
||||
import chat.revolt.api.schemas.Channel
|
||||
import chat.revolt.api.schemas.Message
|
||||
import chat.revolt.api.schemas.MessagesInChannel
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.internals.ULID
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import chat.peptide.api.schemas.Message
|
||||
import chat.peptide.api.schemas.MessagesInChannel
|
||||
import chat.peptide.api.schemas.User
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.header
|
||||
|
|
@ -37,7 +37,7 @@ suspend fun fetchMessagesFromChannel(
|
|||
nearby: String? = null,
|
||||
sort: String? = null
|
||||
): MessagesInChannel {
|
||||
val response = RevoltHttp.get("/channels/$channelId/messages".api()) {
|
||||
val response = PeptideHttp.get("/channels/$channelId/messages".api()) {
|
||||
parameter("limit", limit)
|
||||
parameter("include_users", includeUsers)
|
||||
|
||||
|
|
@ -49,12 +49,12 @@ suspend fun fetchMessagesFromChannel(
|
|||
.bodyAsText()
|
||||
|
||||
if (includeUsers) {
|
||||
return RevoltJson.decodeFromString(
|
||||
return PeptideJson.decodeFromString(
|
||||
MessagesInChannel.serializer(),
|
||||
response
|
||||
)
|
||||
} else {
|
||||
val messages = RevoltJson.decodeFromString(
|
||||
val messages = PeptideJson.decodeFromString(
|
||||
ListSerializer(Message.serializer()),
|
||||
response
|
||||
)
|
||||
|
|
@ -104,7 +104,7 @@ suspend fun sendMessage(
|
|||
attachments: List<String>? = null,
|
||||
idempotencyKey: String = ULID.makeNext()
|
||||
): String {
|
||||
val response = RevoltHttp.post("/channels/$channelId/messages".api()) {
|
||||
val response = PeptideHttp.post("/channels/$channelId/messages".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(
|
||||
SendMessageBody(
|
||||
|
|
@ -122,7 +122,7 @@ suspend fun sendMessage(
|
|||
}
|
||||
|
||||
suspend fun editMessage(channelId: String, messageId: String, newContent: String? = null) {
|
||||
val response = RevoltHttp.patch("/channels/$channelId/messages/$messageId".api()) {
|
||||
val response = PeptideHttp.patch("/channels/$channelId/messages/$messageId".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(
|
||||
EditMessageBody(
|
||||
|
|
@ -133,7 +133,7 @@ suspend fun editMessage(channelId: String, messageId: String, newContent: String
|
|||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Error(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -141,55 +141,55 @@ suspend fun editMessage(channelId: String, messageId: String, newContent: String
|
|||
}
|
||||
|
||||
suspend fun deleteMessage(channelId: String, messageId: String) {
|
||||
RevoltHttp.delete("/channels/$channelId/messages/$messageId".api())
|
||||
PeptideHttp.delete("/channels/$channelId/messages/$messageId".api())
|
||||
}
|
||||
|
||||
suspend fun ackChannel(channelId: String, messageId: String = ULID.makeNext()) {
|
||||
RevoltHttp.put("/channels/$channelId/ack/$messageId".api())
|
||||
PeptideHttp.put("/channels/$channelId/ack/$messageId".api())
|
||||
}
|
||||
|
||||
suspend fun fetchSingleChannel(channelId: String): Channel {
|
||||
val response = RevoltHttp.get("/channels/$channelId".api())
|
||||
val response = PeptideHttp.get("/channels/$channelId".api())
|
||||
.bodyAsText()
|
||||
|
||||
return RevoltJson.decodeFromString(
|
||||
return PeptideJson.decodeFromString(
|
||||
Channel.serializer(),
|
||||
response
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun fetchGroupParticipants(channelId: String): List<User> {
|
||||
val response = RevoltHttp.get("/channels/$channelId/members".api())
|
||||
val response = PeptideHttp.get("/channels/$channelId/members".api())
|
||||
.bodyAsText()
|
||||
|
||||
return RevoltJson.decodeFromString(
|
||||
return PeptideJson.decodeFromString(
|
||||
ListSerializer(User.serializer()),
|
||||
response
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun createInvite(channelId: String): CreateInviteResponse {
|
||||
val response = RevoltHttp.post("/channels/$channelId/invites".api())
|
||||
val response = PeptideHttp.post("/channels/$channelId/invites".api())
|
||||
.bodyAsText()
|
||||
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
if (error.type != "Server") throw Error(error.type)
|
||||
|
||||
return RevoltJson.decodeFromString(CreateInviteResponse.serializer(), response)
|
||||
return PeptideJson.decodeFromString(CreateInviteResponse.serializer(), response)
|
||||
}
|
||||
|
||||
suspend fun fetchSingleMessage(channelId: String, messageId: String): Message {
|
||||
val response = RevoltHttp.get("/channels/$channelId/messages/$messageId".api())
|
||||
val response = PeptideHttp.get("/channels/$channelId/messages/$messageId".api())
|
||||
.bodyAsText()
|
||||
|
||||
return RevoltJson.decodeFromString(
|
||||
return PeptideJson.decodeFromString(
|
||||
Message.serializer(),
|
||||
response
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun leaveDeleteOrCloseChannel(channelId: String, leaveSilently: Boolean = false) {
|
||||
RevoltHttp.delete("/channels/$channelId".api()) {
|
||||
PeptideHttp.delete("/channels/$channelId".api()) {
|
||||
parameter("leave_silently", leaveSilently)
|
||||
}
|
||||
}
|
||||
|
|
@ -207,33 +207,33 @@ suspend fun patchChannel(
|
|||
val body = mutableMapOf<String, JsonElement>()
|
||||
|
||||
if (name != null) {
|
||||
body["name"] = RevoltJson.encodeToJsonElement(String.serializer(), name)
|
||||
body["name"] = PeptideJson.encodeToJsonElement(String.serializer(), name)
|
||||
}
|
||||
|
||||
if (description != null) {
|
||||
body["description"] = RevoltJson.encodeToJsonElement(String.serializer(), description)
|
||||
body["description"] = PeptideJson.encodeToJsonElement(String.serializer(), description)
|
||||
}
|
||||
|
||||
if (icon != null) {
|
||||
body["icon"] = RevoltJson.encodeToJsonElement(String.serializer(), icon)
|
||||
body["icon"] = PeptideJson.encodeToJsonElement(String.serializer(), icon)
|
||||
}
|
||||
|
||||
if (banner != null) {
|
||||
body["banner"] = RevoltJson.encodeToJsonElement(String.serializer(), banner)
|
||||
body["banner"] = PeptideJson.encodeToJsonElement(String.serializer(), banner)
|
||||
}
|
||||
|
||||
if (remove != null) {
|
||||
body["remove"] = RevoltJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
||||
body["remove"] = PeptideJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
||||
}
|
||||
|
||||
if (nsfw != null) {
|
||||
body["nsfw"] = RevoltJson.encodeToJsonElement(Boolean.serializer(), nsfw)
|
||||
body["nsfw"] = PeptideJson.encodeToJsonElement(Boolean.serializer(), nsfw)
|
||||
}
|
||||
|
||||
val response = RevoltHttp.patch("/channels/$channelId".api()) {
|
||||
val response = PeptideHttp.patch("/channels/$channelId".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
MapSerializer(
|
||||
String.serializer(),
|
||||
JsonElement.serializer()
|
||||
|
|
@ -245,14 +245,14 @@ suspend fun patchChannel(
|
|||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
if (!pure) {
|
||||
val channel = RevoltJson.decodeFromString(Channel.serializer(), response)
|
||||
RevoltAPI.channelCache[channelId] = channel
|
||||
val channel = PeptideJson.decodeFromString(Channel.serializer(), response)
|
||||
PeptideAPI.channelCache[channelId] = channel
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package chat.revolt.api.routes.channel
|
||||
package chat.peptide.api.routes.channel
|
||||
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.schemas.Channel
|
||||
import chat.revolt.screens.create.MAX_ADDABLE_PEOPLE_IN_GROUP
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import chat.peptide.screens.create.MAX_ADDABLE_PEOPLE_IN_GROUP
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.put
|
||||
|
|
@ -28,23 +28,23 @@ suspend fun createGroupDM(name: String, members: List<String>): Channel {
|
|||
throw Exception("Too many members, maximum is $MAX_ADDABLE_PEOPLE_IN_GROUP")
|
||||
}
|
||||
|
||||
val response = RevoltHttp.post("/channels/create".api()) {
|
||||
val response = PeptideHttp.post("/channels/create".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(CreateGroupDMBody(name, members))
|
||||
}.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Error(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
return RevoltJson.decodeFromString(Channel.serializer(), response)
|
||||
return PeptideJson.decodeFromString(Channel.serializer(), response)
|
||||
}
|
||||
|
||||
suspend fun removeMember(channelId: String, userId: String) {
|
||||
val response = RevoltHttp.delete("/channels/$channelId/recipients/$userId".api())
|
||||
val response = PeptideHttp.delete("/channels/$channelId/recipients/$userId".api())
|
||||
|
||||
if (!response.status.isSuccess()) {
|
||||
throw Error(response.status.toString())
|
||||
|
|
@ -52,7 +52,7 @@ suspend fun removeMember(channelId: String, userId: String) {
|
|||
}
|
||||
|
||||
suspend fun addMember(channelId: String, userId: String) {
|
||||
val response = RevoltHttp.put("/channels/$channelId/recipients/$userId".api())
|
||||
val response = PeptideHttp.put("/channels/$channelId/recipients/$userId".api())
|
||||
|
||||
if (!response.status.isSuccess()) {
|
||||
throw Error(response.status.toString())
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package chat.peptide.api.routes.channel
|
||||
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.put
|
||||
|
||||
suspend fun react(channelId: String, messageId: String, emoji: String) {
|
||||
PeptideHttp.put("/channels/$channelId/messages/$messageId/reactions/$emoji".api())
|
||||
}
|
||||
|
||||
suspend fun unreact(channelId: String, messageId: String, emoji: String) {
|
||||
PeptideHttp.delete("/channels/$channelId/messages/$messageId/reactions/$emoji".api())
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package chat.peptide.api.routes.custom
|
||||
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.Emoji
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
|
||||
suspend fun fetchEmoji(id: String): Emoji {
|
||||
val response = PeptideHttp.get("/custom/emoji/$id".api()).bodyAsText()
|
||||
return PeptideJson.decodeFromString(
|
||||
Emoji.serializer(),
|
||||
response
|
||||
)
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package chat.revolt.api.routes.googlesheets
|
||||
package chat.peptide.api.routes.googlesheets
|
||||
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -27,7 +27,7 @@ object GoogleSheetsService {
|
|||
crossinline mapper: (Map<String, String>) -> T
|
||||
): List<T> = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val response = RevoltHttp.get(sheetUrl).bodyAsText()
|
||||
val response = PeptideHttp.get(sheetUrl).bodyAsText()
|
||||
|
||||
// Determine if the response is CSV or JSON
|
||||
if (sheetUrl.contains("output=csv") || response.startsWith("\"") || response.contains(",")) {
|
||||
|
|
@ -104,7 +104,7 @@ object GoogleSheetsService {
|
|||
jsonData: String,
|
||||
crossinline mapper: (Map<String, String>) -> T
|
||||
): List<T> {
|
||||
val sheetResponse = RevoltJson.decodeFromString<GoogleSheetResponse>(jsonData)
|
||||
val sheetResponse = PeptideJson.decodeFromString<GoogleSheetResponse>(jsonData)
|
||||
|
||||
// Convert the sheet data to a list of objects
|
||||
val headers = sheetResponse.feed.entry
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.routes.googlesheets
|
||||
package chat.peptide.api.routes.googlesheets
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package chat.peptide.api.routes.invites
|
||||
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.Invite
|
||||
import chat.peptide.api.schemas.InviteJoined
|
||||
import chat.peptide.api.schemas.RsResult
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import kotlinx.serialization.SerializationException
|
||||
|
||||
suspend fun fetchInviteByCode(code: String): RsResult<Invite, PeptideError> {
|
||||
val response = PeptideHttp.get("/invites/$code".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
if (error.type != "Server") return RsResult.err(error)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val invite = PeptideJson.decodeFromString(Invite.serializer(), response)
|
||||
return RsResult.ok(invite)
|
||||
}
|
||||
|
||||
suspend fun joinInviteByCode(code: String): RsResult<InviteJoined, PeptideError> {
|
||||
val response = PeptideHttp.post("/invites/$code".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
if (error.type != "Server") return RsResult.err(error)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val invite = PeptideJson.decodeFromString(InviteJoined.serializer(), response)
|
||||
return RsResult.ok(invite)
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package chat.revolt.api.routes.microservices.autumn
|
||||
package chat.peptide.api.routes.microservices.autumn
|
||||
|
||||
import chat.revolt.api.HitRateLimitException
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.schemas.AutumnError
|
||||
import chat.revolt.api.schemas.AutumnId
|
||||
import chat.peptide.api.HitRateLimitException
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.schemas.AutumnError
|
||||
import chat.peptide.api.schemas.AutumnId
|
||||
import io.ktor.client.plugins.onUpload
|
||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||
import io.ktor.client.request.forms.formData
|
||||
|
|
@ -36,9 +36,9 @@ suspend fun uploadToAutumn(
|
|||
contentType: ContentType,
|
||||
onProgress: (Long, Long) -> Unit = { _, _ -> }
|
||||
): String {
|
||||
val uploadUrl = "${RevoltAPI.getCurrentFilesUrl()}/$tag"
|
||||
val uploadUrl = "${PeptideAPI.getCurrentFilesUrl()}/$tag"
|
||||
|
||||
val response = RevoltHttp.post(uploadUrl) {
|
||||
val response = PeptideHttp.post(uploadUrl) {
|
||||
setBody(
|
||||
MultiPartFormDataContent(
|
||||
formData {
|
||||
|
|
@ -53,18 +53,18 @@ suspend fun uploadToAutumn(
|
|||
}
|
||||
)
|
||||
)
|
||||
header(RevoltAPI.TOKEN_HEADER_NAME, RevoltAPI.sessionToken)
|
||||
header(PeptideAPI.TOKEN_HEADER_NAME, PeptideAPI.sessionToken)
|
||||
onUpload { bytesSentTotal, contentLength ->
|
||||
contentLength?.let { onProgress(bytesSentTotal, it) }
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val autumnId = RevoltJson.decodeFromString(AutumnId.serializer(), response.bodyAsText())
|
||||
val autumnId = PeptideJson.decodeFromString(AutumnId.serializer(), response.bodyAsText())
|
||||
return autumnId.id
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(AutumnError.serializer(), response.bodyAsText())
|
||||
val error = PeptideJson.decodeFromString(AutumnError.serializer(), response.bodyAsText())
|
||||
throw Exception(error.type)
|
||||
} catch (e: Exception) {
|
||||
if (response.status == HttpStatusCode.TooManyRequests) {
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package chat.revolt.api.routes.microservices.geo
|
||||
package chat.peptide.api.routes.microservices.geo
|
||||
|
||||
import chat.revolt.api.HitRateLimitException
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.buildUserAgent
|
||||
import chat.peptide.api.HitRateLimitException
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.buildUserAgent
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
|
|
@ -18,12 +18,12 @@ data class GeoResponse(
|
|||
|
||||
suspend fun queryGeo(): GeoResponse {
|
||||
try {
|
||||
val response = RevoltHttp.get("https://geo.revolt.chat/?client=android") {
|
||||
val response = PeptideHttp.get("https://geo.peptide.chat/?client=android") {
|
||||
header("User-Agent", buildUserAgent("Ktor queryGeo"))
|
||||
}
|
||||
|
||||
if (response.status == HttpStatusCode.OK) {
|
||||
return RevoltJson.decodeFromString(response.bodyAsText())
|
||||
return PeptideJson.decodeFromString(response.bodyAsText())
|
||||
} else throw Exception("Failed to query geo: ${response.status.value} ${response.status.description}")
|
||||
} catch (e: Exception) {
|
||||
throw Exception("Failed to query geo: ${e.message}", e).also {
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package chat.peptide.api.routes.microservices.health
|
||||
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.schemas.HealthNotice
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
|
||||
suspend fun healthCheck(): HealthNotice {
|
||||
val response = PeptideHttp.get("https://health.peptide.chat/api/health").bodyAsText()
|
||||
return PeptideJson.decodeFromString(HealthNotice.serializer(), response)
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package chat.peptide.api.routes.microservices.january
|
||||
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import java.net.URLEncoder
|
||||
|
||||
fun asJanuaryProxyUrl(url: String): String {
|
||||
return "${PeptideAPI.getCurrentJanuaryUrl()}/proxy?url=${URLEncoder.encode(url, "utf-8")}"
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package chat.revolt.api.routes.misc
|
||||
package chat.peptide.api.routes.misc
|
||||
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import kotlinx.serialization.SerialName
|
||||
|
|
@ -9,7 +9,7 @@ import kotlinx.serialization.Serializable
|
|||
|
||||
@Serializable
|
||||
data class Root(
|
||||
val revolt: String,
|
||||
val peptide: String,
|
||||
val features: Features,
|
||||
val ws: String,
|
||||
val app: String,
|
||||
|
|
@ -61,5 +61,5 @@ data class LiveKitNode(
|
|||
)
|
||||
|
||||
suspend fun getRootRoute(): Root {
|
||||
return RevoltHttp.get("/".api()).body()
|
||||
return PeptideHttp.get("/".api()).body()
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package chat.revolt.api.routes.onboard
|
||||
package chat.peptide.api.routes.onboard
|
||||
|
||||
import chat.revolt.api.RateLimitResponse
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.schemas.RsResult
|
||||
import chat.peptide.api.RateLimitResponse
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.RsResult
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.client.request.post
|
||||
|
|
@ -23,22 +23,22 @@ data class OnboardingResponse(
|
|||
val onboarding: Boolean
|
||||
)
|
||||
|
||||
suspend fun needsOnboarding(sessionToken: String = RevoltAPI.sessionToken): Boolean {
|
||||
val response = RevoltHttp.get("/onboard/hello".api()) {
|
||||
header(RevoltAPI.TOKEN_HEADER_NAME, sessionToken)
|
||||
suspend fun needsOnboarding(sessionToken: String = PeptideAPI.sessionToken): Boolean {
|
||||
val response = PeptideHttp.get("/onboard/hello".api()) {
|
||||
header(PeptideAPI.TOKEN_HEADER_NAME, sessionToken)
|
||||
}
|
||||
|
||||
val responseContent = response.bodyAsText()
|
||||
|
||||
try {
|
||||
val rateLimitResponse =
|
||||
RevoltJson.decodeFromString(RateLimitResponse.serializer(), responseContent)
|
||||
PeptideJson.decodeFromString(RateLimitResponse.serializer(), responseContent)
|
||||
throw rateLimitResponse.toException()
|
||||
} catch (e: SerializationException) {
|
||||
// good path
|
||||
}
|
||||
|
||||
return RevoltJson.decodeFromString(OnboardingResponse.serializer(), responseContent).onboarding
|
||||
return PeptideJson.decodeFromString(OnboardingResponse.serializer(), responseContent).onboarding
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
@ -48,26 +48,26 @@ data class OnboardingCompletionBody(
|
|||
|
||||
suspend fun completeOnboarding(
|
||||
body: OnboardingCompletionBody,
|
||||
sessionToken: String = RevoltAPI.sessionToken
|
||||
): RsResult<Unit, RevoltError> {
|
||||
val response = RevoltHttp.post("/onboard/complete".api()) {
|
||||
sessionToken: String = PeptideAPI.sessionToken
|
||||
): RsResult<Unit, PeptideError> {
|
||||
val response = PeptideHttp.post("/onboard/complete".api()) {
|
||||
setBody(body)
|
||||
contentType(ContentType.Application.Json)
|
||||
header(RevoltAPI.TOKEN_HEADER_NAME, sessionToken)
|
||||
header(PeptideAPI.TOKEN_HEADER_NAME, sessionToken)
|
||||
}
|
||||
|
||||
if (response.status == HttpStatusCode.Conflict) {
|
||||
return RsResult.err(RevoltError("UsernameTaken"))
|
||||
return RsResult.err(PeptideError("UsernameTaken"))
|
||||
}
|
||||
|
||||
if (response.status == HttpStatusCode.BadRequest) {
|
||||
return RsResult.err(RevoltError("InvalidUsername"))
|
||||
return RsResult.err(PeptideError("InvalidUsername"))
|
||||
}
|
||||
|
||||
val responseContent = response.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), responseContent)
|
||||
return RsResult.err(error)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package chat.revolt.api.routes.push
|
||||
package chat.peptide.api.routes.push
|
||||
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.routes.account.WebPushData
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.routes.account.WebPushData
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.http.ContentType
|
||||
|
|
@ -19,7 +19,7 @@ suspend fun subscribePush(
|
|||
auth = auth
|
||||
)
|
||||
|
||||
RevoltHttp.post("/push/subscribe".api()) {
|
||||
PeptideHttp.post("/push/subscribe".api()) {
|
||||
setBody(data)
|
||||
contentType(ContentType.Application.Json)
|
||||
}
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
package chat.revolt.api.routes.safety
|
||||
package chat.peptide.api.routes.safety
|
||||
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.schemas.ContentReportReason
|
||||
import chat.revolt.api.schemas.FullMessageReport
|
||||
import chat.revolt.api.schemas.FullServerReport
|
||||
import chat.revolt.api.schemas.FullUserReport
|
||||
import chat.revolt.api.schemas.MessageReport
|
||||
import chat.revolt.api.schemas.ServerReport
|
||||
import chat.revolt.api.schemas.UserReport
|
||||
import chat.revolt.api.schemas.UserReportReason
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.schemas.ContentReportReason
|
||||
import chat.peptide.api.schemas.FullMessageReport
|
||||
import chat.peptide.api.schemas.FullServerReport
|
||||
import chat.peptide.api.schemas.FullUserReport
|
||||
import chat.peptide.api.schemas.MessageReport
|
||||
import chat.peptide.api.schemas.ServerReport
|
||||
import chat.peptide.api.schemas.UserReport
|
||||
import chat.peptide.api.schemas.UserReportReason
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
|
|
@ -31,9 +31,9 @@ suspend fun putMessageReport(
|
|||
additional_context = additionalContext
|
||||
)
|
||||
|
||||
val response = RevoltHttp.post("/safety/report".api()) {
|
||||
val response = PeptideHttp.post("/safety/report".api()) {
|
||||
setBody(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
FullMessageReport.serializer(),
|
||||
fullMessageReport
|
||||
)
|
||||
|
|
@ -42,7 +42,7 @@ suspend fun putMessageReport(
|
|||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Error(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -63,9 +63,9 @@ suspend fun putServerReport(
|
|||
additional_context = additionalContext
|
||||
)
|
||||
|
||||
val response = RevoltHttp.post("/safety/report".api()) {
|
||||
val response = PeptideHttp.post("/safety/report".api()) {
|
||||
setBody(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
FullServerReport.serializer(),
|
||||
fullServerReport
|
||||
)
|
||||
|
|
@ -74,7 +74,7 @@ suspend fun putServerReport(
|
|||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Error(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -95,9 +95,9 @@ suspend fun putUserReport(
|
|||
additional_context = additionalContext
|
||||
)
|
||||
|
||||
val response = RevoltHttp.post("/safety/report".api()) {
|
||||
val response = PeptideHttp.post("/safety/report".api()) {
|
||||
setBody(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
FullUserReport.serializer(),
|
||||
fullUserReport
|
||||
)
|
||||
|
|
@ -106,7 +106,7 @@ suspend fun putUserReport(
|
|||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Error(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package chat.revolt.api.routes.server
|
||||
package chat.peptide.api.routes.server
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.schemas.Member
|
||||
import chat.revolt.api.schemas.ServerWithChannelObjects
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.Member
|
||||
import chat.peptide.api.schemas.ServerWithChannelObjects
|
||||
import chat.peptide.api.schemas.User
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
|
|
@ -25,7 +25,7 @@ data class FetchMembersResponse(
|
|||
)
|
||||
|
||||
suspend fun ackServer(serverId: String) {
|
||||
RevoltHttp.put("/servers/$serverId/ack".api())
|
||||
PeptideHttp.put("/servers/$serverId/ack".api())
|
||||
}
|
||||
|
||||
suspend fun fetchMembers(
|
||||
|
|
@ -33,55 +33,55 @@ suspend fun fetchMembers(
|
|||
includeOffline: Boolean = false,
|
||||
pure: Boolean = false
|
||||
): FetchMembersResponse {
|
||||
val response = RevoltHttp.get("/servers/$serverId/members".api()) {
|
||||
val response = PeptideHttp.get("/servers/$serverId/members".api()) {
|
||||
parameter("exclude_offline", !includeOffline)
|
||||
}
|
||||
|
||||
val responseContent = response.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), responseContent)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), responseContent)
|
||||
throw Error(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val membersResponse =
|
||||
RevoltJson.decodeFromString(FetchMembersResponse.serializer(), responseContent)
|
||||
PeptideJson.decodeFromString(FetchMembersResponse.serializer(), responseContent)
|
||||
|
||||
if (pure) {
|
||||
return membersResponse
|
||||
}
|
||||
|
||||
membersResponse.members.forEach { member ->
|
||||
if (!RevoltAPI.members.hasMember(serverId, member.id!!.user)) {
|
||||
RevoltAPI.members.setMember(serverId, member)
|
||||
if (!PeptideAPI.members.hasMember(serverId, member.id!!.user)) {
|
||||
PeptideAPI.members.setMember(serverId, member)
|
||||
}
|
||||
}
|
||||
|
||||
membersResponse.users.forEach { user ->
|
||||
user.id?.let { RevoltAPI.userCache.putIfAbsent(it, user) }
|
||||
user.id?.let { PeptideAPI.userCache.putIfAbsent(it, user) }
|
||||
}
|
||||
|
||||
return membersResponse
|
||||
}
|
||||
|
||||
suspend fun fetchMember(serverId: String, userId: String, pure: Boolean = false): Member {
|
||||
val response = RevoltHttp.get("/servers/$serverId/members/$userId".api())
|
||||
val response = PeptideHttp.get("/servers/$serverId/members/$userId".api())
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response.bodyAsText())
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val member = RevoltJson.decodeFromString(Member.serializer(), response.bodyAsText())
|
||||
val member = PeptideJson.decodeFromString(Member.serializer(), response.bodyAsText())
|
||||
|
||||
if (!pure) {
|
||||
member.id?.let {
|
||||
if (!RevoltAPI.members.hasMember(serverId, it.user)) {
|
||||
RevoltAPI.members.setMember(serverId, member)
|
||||
if (!PeptideAPI.members.hasMember(serverId, it.user)) {
|
||||
PeptideAPI.members.setMember(serverId, member)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ suspend fun fetchMember(serverId: String, userId: String, pure: Boolean = false)
|
|||
}
|
||||
|
||||
suspend fun leaveOrDeleteServer(serverId: String, leaveSilently: Boolean = false) {
|
||||
RevoltHttp.delete("/servers/$serverId".api()) {
|
||||
PeptideHttp.delete("/servers/$serverId".api()) {
|
||||
parameter("leave_silently", leaveSilently)
|
||||
}
|
||||
}
|
||||
|
|
@ -109,16 +109,16 @@ suspend fun createServer(
|
|||
): ServerWithChannelObjects {
|
||||
val body = ServerCreationBody(name, description, nsfw)
|
||||
|
||||
val response = RevoltHttp.post("/servers/create".api()) {
|
||||
setBody(RevoltJson.encodeToString(ServerCreationBody.serializer(), body))
|
||||
val response = PeptideHttp.post("/servers/create".api()) {
|
||||
setBody(PeptideJson.encodeToString(ServerCreationBody.serializer(), body))
|
||||
}
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response.bodyAsText())
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response.bodyAsText())
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
return RevoltJson.decodeFromString(ServerWithChannelObjects.serializer(), response.bodyAsText())
|
||||
return PeptideJson.decodeFromString(ServerWithChannelObjects.serializer(), response.bodyAsText())
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package chat.revolt.api.routes.sync
|
||||
package chat.peptide.api.routes.sync
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
|
|
@ -17,13 +17,13 @@ import kotlinx.serialization.json.JsonArray
|
|||
@Serializable
|
||||
data class SyncedSetting(val timestamp: Long, val value: String)
|
||||
|
||||
suspend fun getKeys(vararg keys: String, revoltToken: String): Map<String, SyncedSetting> {
|
||||
val response = RevoltHttp.post("/sync/settings/fetch".api()) {
|
||||
headers.append(RevoltAPI.TOKEN_HEADER_NAME, revoltToken)
|
||||
suspend fun getKeys(vararg keys: String, peptideToken: String): Map<String, SyncedSetting> {
|
||||
val response = PeptideHttp.post("/sync/settings/fetch".api()) {
|
||||
headers.append(PeptideAPI.TOKEN_HEADER_NAME, peptideToken)
|
||||
|
||||
// format: {"keys": ["key1", "key2"]}
|
||||
setBody(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
MapSerializer(
|
||||
String.serializer(),
|
||||
ListSerializer(String.serializer())
|
||||
|
|
@ -33,7 +33,7 @@ suspend fun getKeys(vararg keys: String, revoltToken: String): Map<String, Synce
|
|||
)
|
||||
}.bodyAsText()
|
||||
|
||||
return RevoltJson.decodeFromString(
|
||||
return PeptideJson.decodeFromString(
|
||||
MapSerializer(
|
||||
String.serializer(),
|
||||
JsonArray.serializer()
|
||||
|
|
@ -46,22 +46,22 @@ suspend fun getKeys(vararg keys: String, revoltToken: String): Map<String, Synce
|
|||
.toString()
|
||||
.removeSurrounding("\"")
|
||||
.replace("\\\"", "\"")
|
||||
.replace("\\\\", "\\") // the revolt API is so scuffed i can't even make this up
|
||||
.replace("\\\\", "\\") // the peptide API is so scuffed i can't even make this up
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getKeys(vararg keys: String): Map<String, SyncedSetting> {
|
||||
return getKeys(*keys, revoltToken = RevoltAPI.sessionToken)
|
||||
return getKeys(*keys, peptideToken = PeptideAPI.sessionToken)
|
||||
}
|
||||
|
||||
suspend fun setKey(key: String, value: String) {
|
||||
RevoltHttp.post("/sync/settings/set".api()) {
|
||||
PeptideHttp.post("/sync/settings/set".api()) {
|
||||
parameter("timestamp", System.currentTimeMillis())
|
||||
|
||||
// format: {"key": "value"}
|
||||
setBody(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
MapSerializer(
|
||||
String.serializer(),
|
||||
String.serializer()
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
package chat.revolt.api.routes.sync
|
||||
package chat.peptide.api.routes.sync
|
||||
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.schemas.ChannelUnreadResponse
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.ChannelUnreadResponse
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import kotlinx.serialization.builtins.ListSerializer
|
||||
|
||||
suspend fun syncUnreads(): List<ChannelUnreadResponse> {
|
||||
val response = RevoltHttp.get("/sync/unreads".api())
|
||||
val response = PeptideHttp.get("/sync/unreads".api())
|
||||
.bodyAsText()
|
||||
|
||||
return RevoltJson.decodeFromString(
|
||||
return PeptideJson.decodeFromString(
|
||||
ListSerializer(ChannelUnreadResponse.serializer()),
|
||||
response
|
||||
)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package chat.peptide.api.routes.user
|
||||
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.Channel
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import kotlinx.serialization.SerializationException
|
||||
|
||||
suspend fun openDM(userId: String): Channel {
|
||||
val response = PeptideHttp.get("/users/$userId/dm".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Error(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
return PeptideJson.decodeFromString(Channel.serializer(), response)
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package chat.revolt.api.routes.user
|
||||
package chat.peptide.api.routes.user
|
||||
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.put
|
||||
|
|
@ -14,11 +14,11 @@ import io.ktor.http.contentType
|
|||
import kotlinx.serialization.SerializationException
|
||||
|
||||
suspend fun blockUser(userId: String) {
|
||||
val response = RevoltHttp.put("/users/$userId/block".api())
|
||||
val response = PeptideHttp.put("/users/$userId/block".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -26,11 +26,11 @@ suspend fun blockUser(userId: String) {
|
|||
}
|
||||
|
||||
suspend fun unblockUser(userId: String) {
|
||||
val response = RevoltHttp.delete("/users/$userId/block".api())
|
||||
val response = PeptideHttp.delete("/users/$userId/block".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -38,14 +38,14 @@ suspend fun unblockUser(userId: String) {
|
|||
}
|
||||
|
||||
suspend fun friendUser(username: String) {
|
||||
val response = RevoltHttp.post("/users/friend".api()) {
|
||||
val response = PeptideHttp.post("/users/friend".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(mapOf("username" to username))
|
||||
}
|
||||
val body = response.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), body)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), body)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -53,11 +53,11 @@ suspend fun friendUser(username: String) {
|
|||
}
|
||||
|
||||
suspend fun acceptFriendRequest(userId: String) {
|
||||
val response = RevoltHttp.put("/users/$userId/friend".api())
|
||||
val response = PeptideHttp.put("/users/$userId/friend".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -65,11 +65,11 @@ suspend fun acceptFriendRequest(userId: String) {
|
|||
}
|
||||
|
||||
suspend fun unfriendUser(userId: String) {
|
||||
val response = RevoltHttp.delete("/users/$userId/friend".api())
|
||||
val response = PeptideHttp.delete("/users/$userId/friend".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package chat.revolt.api.routes.user
|
||||
package chat.peptide.api.routes.user
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.revolt.api.schemas.Profile
|
||||
import chat.revolt.api.schemas.Status
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import chat.peptide.api.schemas.Profile
|
||||
import chat.peptide.api.schemas.Status
|
||||
import chat.peptide.api.schemas.User
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.patch
|
||||
import io.ktor.client.request.setBody
|
||||
|
|
@ -21,24 +21,24 @@ import kotlinx.serialization.builtins.serializer
|
|||
import kotlinx.serialization.json.JsonElement
|
||||
|
||||
suspend fun fetchSelf(): User {
|
||||
val response = RevoltHttp.get("/users/@me".api())
|
||||
val response = PeptideHttp.get("/users/@me".api())
|
||||
.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val user = RevoltJson.decodeFromString(User.serializer(), response)
|
||||
val user = PeptideJson.decodeFromString(User.serializer(), response)
|
||||
|
||||
if (user.id == null) {
|
||||
throw Exception("Self user ID is null")
|
||||
}
|
||||
|
||||
RevoltAPI.userCache[user.id] = user
|
||||
RevoltAPI.selfId = user.id
|
||||
PeptideAPI.userCache[user.id] = user
|
||||
PeptideAPI.selfId = user.id
|
||||
|
||||
return user
|
||||
}
|
||||
|
|
@ -54,11 +54,11 @@ suspend fun patchSelf(
|
|||
val body = mutableMapOf<String, JsonElement>()
|
||||
|
||||
if (status != null) {
|
||||
body["status"] = RevoltJson.encodeToJsonElement(Status.serializer(), status)
|
||||
body["status"] = PeptideJson.encodeToJsonElement(Status.serializer(), status)
|
||||
}
|
||||
|
||||
if (avatar != null) {
|
||||
body["avatar"] = RevoltJson.encodeToJsonElement(String.serializer(), avatar)
|
||||
body["avatar"] = PeptideJson.encodeToJsonElement(String.serializer(), avatar)
|
||||
}
|
||||
|
||||
if (background != null || bio != null) {
|
||||
|
|
@ -71,7 +71,7 @@ suspend fun patchSelf(
|
|||
profileMap["content"] = bio
|
||||
}
|
||||
|
||||
body["profile"] = RevoltJson.encodeToJsonElement(
|
||||
body["profile"] = PeptideJson.encodeToJsonElement(
|
||||
MapSerializer(
|
||||
String.serializer(),
|
||||
String.serializer()
|
||||
|
|
@ -81,13 +81,13 @@ suspend fun patchSelf(
|
|||
}
|
||||
|
||||
if (remove != null) {
|
||||
body["remove"] = RevoltJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
||||
body["remove"] = PeptideJson.encodeToJsonElement(ListSerializer(String.serializer()), remove)
|
||||
}
|
||||
|
||||
val response = RevoltHttp.patch("/users/@me".api()) {
|
||||
val response = PeptideHttp.patch("/users/@me".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(
|
||||
RevoltJson.encodeToString(
|
||||
PeptideJson.encodeToString(
|
||||
MapSerializer(
|
||||
String.serializer(),
|
||||
JsonElement.serializer()
|
||||
|
|
@ -98,21 +98,21 @@ suspend fun patchSelf(
|
|||
}
|
||||
.bodyAsText()
|
||||
|
||||
if (RevoltAPI.selfId == null) {
|
||||
if (PeptideAPI.selfId == null) {
|
||||
throw Error("Self ID is null")
|
||||
}
|
||||
|
||||
val currentUser = RevoltAPI.userCache[RevoltAPI.selfId] ?: fetchSelf()
|
||||
val newUserKeys = RevoltJson.decodeFromString(User.serializer(), response)
|
||||
val currentUser = PeptideAPI.userCache[PeptideAPI.selfId] ?: fetchSelf()
|
||||
val newUserKeys = PeptideJson.decodeFromString(User.serializer(), response)
|
||||
val mergedUser = currentUser.mergeWithPartial(newUserKeys)
|
||||
|
||||
if (!pure) {
|
||||
RevoltAPI.userCache[RevoltAPI.selfId!!] = mergedUser
|
||||
PeptideAPI.userCache[PeptideAPI.selfId!!] = mergedUser
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun fetchUser(id: String): User {
|
||||
val res = RevoltHttp.get("/users/$id".api())
|
||||
val res = PeptideHttp.get("/users/$id".api())
|
||||
|
||||
if (res.status.value == 404) {
|
||||
return User.getPlaceholder(id)
|
||||
|
|
@ -121,42 +121,42 @@ suspend fun fetchUser(id: String): User {
|
|||
val response = res.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
val user = RevoltJson.decodeFromString(User.serializer(), response)
|
||||
val user = PeptideJson.decodeFromString(User.serializer(), response)
|
||||
|
||||
user.id?.let {
|
||||
RevoltAPI.userCache[it] = user
|
||||
PeptideAPI.userCache[it] = user
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
suspend fun getOrFetchUser(id: String): User {
|
||||
return RevoltAPI.userCache[id] ?: fetchUser(id)
|
||||
return PeptideAPI.userCache[id] ?: fetchUser(id)
|
||||
}
|
||||
|
||||
suspend fun addUserIfUnknown(id: String) {
|
||||
if (RevoltAPI.userCache[id] == null) {
|
||||
RevoltAPI.userCache[id] = fetchUser(id)
|
||||
if (PeptideAPI.userCache[id] == null) {
|
||||
PeptideAPI.userCache[id] = fetchUser(id)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun fetchUserProfile(id: String): Profile {
|
||||
val res = RevoltHttp.get("/users/$id/profile".api())
|
||||
val res = PeptideHttp.get("/users/$id/profile".api())
|
||||
|
||||
val response = res.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
return RevoltJson.decodeFromString(Profile.serializer(), response)
|
||||
return PeptideJson.decodeFromString(Profile.serializer(), response)
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package chat.revolt.api.routes.voice
|
||||
package chat.peptide.api.routes.voice
|
||||
|
||||
import chat.revolt.api.RevoltError
|
||||
import chat.revolt.api.RevoltHttp
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.api
|
||||
import chat.peptide.api.PeptideError
|
||||
import chat.peptide.api.PeptideHttp
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.api
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
|
|
@ -19,17 +19,17 @@ data class JoinCallResponse(
|
|||
)
|
||||
|
||||
suspend fun joinCall(channelId: String, nodeName: String): JoinCallResponse {
|
||||
val response = RevoltHttp.post("/channels/$channelId/join_call".api()) {
|
||||
val response = PeptideHttp.post("/channels/$channelId/join_call".api()) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(mapOf("node" to nodeName))
|
||||
}.bodyAsText()
|
||||
|
||||
try {
|
||||
val error = RevoltJson.decodeFromString(RevoltError.serializer(), response)
|
||||
val error = PeptideJson.decodeFromString(PeptideError.serializer(), response)
|
||||
throw Exception(error.type)
|
||||
} catch (e: SerializationException) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
return RevoltJson.decodeFromString(JoinCallResponse.serializer(), response)
|
||||
return PeptideJson.decodeFromString(JoinCallResponse.serializer(), response)
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -10,6 +10,6 @@ data class Session(
|
|||
val name: String
|
||||
) {
|
||||
fun isCurrent(): Boolean {
|
||||
return id == RevoltAPI.sessionId
|
||||
return id == PeptideAPI.sessionId
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.KSerializer
|
||||
|
|
@ -111,7 +111,7 @@ enum class ChannelType(val value: String) {
|
|||
override val descriptor: SerialDescriptor
|
||||
get() {
|
||||
return PrimitiveSerialDescriptor(
|
||||
"chat.revolt.api.schemas.ChannelType",
|
||||
"chat.peptide.api.schemas.ChannelType",
|
||||
PrimitiveKind.STRING
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -51,10 +51,10 @@ data class InviteJoined(
|
|||
|
||||
fun Uri.isInviteUri(): Boolean {
|
||||
val firstPathSegmentIsInvite = this.pathSegments.firstOrNull() == "invite"
|
||||
val isAppRevoltChat = this.host == RevoltAPI.getCurrentAppUrl().toUri().host
|
||||
val matchRvltGG = this.host == RevoltAPI.getCurrentInvitesUrl().toUri().host
|
||||
val isAppPeptideChat = this.host == PeptideAPI.getCurrentAppUrl().toUri().host
|
||||
val matchRvltGG = this.host == PeptideAPI.getCurrentInvitesUrl().toUri().host
|
||||
|
||||
val matchApp = isAppRevoltChat && firstPathSegmentIsInvite
|
||||
val matchApp = isAppPeptideChat && firstPathSegmentIsInvite
|
||||
|
||||
val hasEnoughSegments =
|
||||
if (matchApp) this.pathSegments.size == 2 else this.pathSegments.size == 1
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -24,14 +24,14 @@ data class Message(
|
|||
val interactions: InteractionsDescription? = null,
|
||||
val pinned: Boolean? = null,
|
||||
/**
|
||||
* See [chat.revolt.api.internals.MessageFlag]
|
||||
* See [chat.peptide.api.internals.MessageFlag]
|
||||
*/
|
||||
val flags: Int? = null,
|
||||
val type: String? = null, // this is _only_ used for websocket events!
|
||||
val tail: Boolean? = null // this is used to determine if the message is the last in a message group
|
||||
) {
|
||||
fun getAuthor(): User? {
|
||||
return author?.let { RevoltAPI.userCache[it] }
|
||||
return author?.let { PeptideAPI.userCache[it] }
|
||||
}
|
||||
|
||||
fun mergeWithPartial(partial: Message): Message {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -29,7 +29,7 @@ enum class ContentReportReason(val value: String) {
|
|||
override val descriptor: SerialDescriptor
|
||||
get() {
|
||||
return PrimitiveSerialDescriptor(
|
||||
"chat.revolt.api.schemas.ContentReportReason",
|
||||
"chat.peptide.api.schemas.ContentReportReason",
|
||||
PrimitiveKind.STRING
|
||||
)
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ enum class UserReportReason(val value: String) {
|
|||
override val descriptor: SerialDescriptor
|
||||
get() {
|
||||
return PrimitiveSerialDescriptor(
|
||||
"chat.revolt.api.schemas.UserReportReason",
|
||||
"chat.peptide.api.schemas.UserReportReason",
|
||||
PrimitiveKind.STRING
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import chat.revolt.ui.theme.OverridableColourScheme
|
||||
import chat.peptide.ui.theme.OverridableColourScheme
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ data class AndroidSpecificSettingsSpecialEmbedSettings(
|
|||
data class AndroidSpecificSettings(
|
||||
/**
|
||||
* The theme to use for the app.
|
||||
* Can be one of `{ None, Revolt, Light, M3Dynamic, Amoled }`
|
||||
* Can be one of `{ None, Peptide, Light, M3Dynamic, Amoled }`
|
||||
*/
|
||||
var theme: String? = null,
|
||||
/**
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
// Result class similar to Rust std::result::Result
|
||||
data class RsResult<V, E>(val value: V?, val error: E?) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.schemas
|
||||
package chat.peptide.api.schemas
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package chat.revolt.api.settings
|
||||
package chat.peptide.api.settings
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import chat.revolt.BuildConfig
|
||||
import chat.revolt.RevoltApplication
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.peptide.BuildConfig
|
||||
import chat.peptide.PeptideApplication
|
||||
import chat.peptide.persistence.KVStorage
|
||||
|
||||
class ExperimentInstance(default: Boolean) {
|
||||
private var _isEnabled by mutableStateOf(default)
|
||||
|
|
@ -31,7 +31,7 @@ object Experiments {
|
|||
val enableServerIdentityOptions = ExperimentInstance(false)
|
||||
|
||||
suspend fun hydrateWithKv() {
|
||||
val kvStorage = KVStorage(RevoltApplication.instance)
|
||||
val kvStorage = KVStorage(PeptideApplication.instance)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
LoadedSettings.experimentsEnabled = true
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package chat.revolt.api.settings
|
||||
package chat.peptide.api.settings
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.SpecialUsers
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.SpecialUsers
|
||||
|
||||
annotation class FeatureFlag(val name: String)
|
||||
annotation class Treatment(val description: String)
|
||||
|
|
@ -60,7 +60,7 @@ object FeatureFlags {
|
|||
@FeatureFlag("LabsAccessControl")
|
||||
var labsAccessControl by mutableStateOf<LabsAccessControlVariates>(
|
||||
LabsAccessControlVariates.Restricted {
|
||||
RevoltAPI.selfId == SpecialUsers.JENNIFER
|
||||
PeptideAPI.selfId == SpecialUsers.JENNIFER
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ object FeatureFlags {
|
|||
@FeatureFlag("UserCards")
|
||||
var userCards by mutableStateOf<UserCardsVariates>(
|
||||
UserCardsVariates.Restricted {
|
||||
RevoltAPI.selfId?.endsWith("Z") == true
|
||||
PeptideAPI.selfId?.endsWith("Z") == true
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package chat.revolt.api.settings
|
||||
package chat.peptide.api.settings
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import chat.revolt.api.routes.microservices.geo.GeoResponse
|
||||
import chat.peptide.api.routes.microservices.geo.GeoResponse
|
||||
|
||||
object GeoStateProvider {
|
||||
var geoState by mutableStateOf<GeoResponse?>(null)
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package chat.revolt.api.settings
|
||||
package chat.peptide.api.settings
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import chat.revolt.api.schemas.AndroidSpecificSettingsSpecialEmbedSettings
|
||||
import chat.revolt.ui.theme.Theme
|
||||
import chat.revolt.ui.theme.getDefaultTheme
|
||||
import chat.peptide.api.schemas.AndroidSpecificSettingsSpecialEmbedSettings
|
||||
import chat.peptide.ui.theme.Theme
|
||||
import chat.peptide.ui.theme.getDefaultTheme
|
||||
|
||||
enum class MessageReplyStyle {
|
||||
None,
|
||||
|
|
@ -25,12 +25,16 @@ object LoadedSettings {
|
|||
var poorlyFormedSettingsKeys by mutableStateOf(emptySet<String>())
|
||||
|
||||
fun hydrateWithSettings(settings: SyncedSettings) {
|
||||
this.theme = settings.android.theme?.let { Theme.valueOf(it) } ?: getDefaultTheme()
|
||||
this.messageReplyStyle =
|
||||
settings.android.messageReplyStyle?.let { MessageReplyStyle.valueOf(it) }
|
||||
?: MessageReplyStyle.SwipeFromEnd
|
||||
this.avatarRadius = settings.android.avatarRadius ?: 50
|
||||
this.specialEmbedSettings = settings.android.specialEmbedSettings ?: SpecialEmbedSettings()
|
||||
try {
|
||||
this.theme = settings.android.theme?.let { Theme.valueOf(it) } ?: getDefaultTheme()
|
||||
this.messageReplyStyle =
|
||||
settings.android.messageReplyStyle?.let { MessageReplyStyle.valueOf(it) }
|
||||
?: MessageReplyStyle.SwipeFromEnd
|
||||
this.avatarRadius = settings.android.avatarRadius ?: 50
|
||||
this.specialEmbedSettings = settings.android.specialEmbedSettings ?: SpecialEmbedSettings()
|
||||
} catch (_: Exception) {
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.api.settings
|
||||
package chat.peptide.api.settings
|
||||
|
||||
object NotificationSettingsProvider {
|
||||
fun isChannelMuted(channelId: String, serverId: String?): Boolean {
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package chat.peptide.api.settings
|
||||
|
||||
enum class NotificationType(val storageValue: String) {
|
||||
DEFAULT("default"),
|
||||
MUTED("muted"),
|
||||
ALL("all"),
|
||||
MENTIONS_ONLY("mentions"),
|
||||
NONE("none");
|
||||
|
||||
companion object {
|
||||
fun fromStorage(value: String?): NotificationType {
|
||||
return when (value) {
|
||||
null -> DEFAULT
|
||||
"default" -> DEFAULT
|
||||
"muted" -> MUTED
|
||||
"all" -> ALL
|
||||
"mentions" -> MENTIONS_ONLY
|
||||
"none" -> NONE
|
||||
else -> DEFAULT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
package chat.revolt.api.settings
|
||||
package chat.peptide.api.settings
|
||||
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.routes.sync.getKeys
|
||||
import chat.revolt.api.routes.sync.setKey
|
||||
import chat.revolt.api.schemas.AndroidSpecificSettings
|
||||
import chat.revolt.api.schemas.NotificationSettings
|
||||
import chat.revolt.api.schemas.OrderingSettings
|
||||
import chat.revolt.api.schemas._NotificationSettingsToParse
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.routes.sync.getKeys
|
||||
import chat.peptide.api.routes.sync.setKey
|
||||
import chat.peptide.api.schemas.AndroidSpecificSettings
|
||||
import chat.peptide.api.schemas.NotificationSettings
|
||||
import chat.peptide.api.schemas.OrderingSettings
|
||||
import chat.peptide.api.schemas._NotificationSettingsToParse
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import logcat.LogPriority
|
||||
|
|
@ -40,14 +40,14 @@ object SyncedSettings {
|
|||
val notifications: NotificationSettings
|
||||
get() = _notifications.value
|
||||
|
||||
suspend fun fetch(revoltToken: String = RevoltAPI.sessionToken) {
|
||||
suspend fun fetch(peptideToken: String = PeptideAPI.sessionToken) {
|
||||
try {
|
||||
val settings =
|
||||
getKeys("ordering", "android", "notifications", revoltToken = revoltToken)
|
||||
getKeys("ordering", "android", "notifications", peptideToken = peptideToken)
|
||||
|
||||
settings["ordering"]?.let {
|
||||
try {
|
||||
_ordering.value = RevoltJson.decodeFromString(
|
||||
_ordering.value = PeptideJson.decodeFromString(
|
||||
OrderingSettings.serializer(),
|
||||
it.value
|
||||
)
|
||||
|
|
@ -59,7 +59,7 @@ object SyncedSettings {
|
|||
|
||||
settings["android"]?.let {
|
||||
try {
|
||||
_android.value = RevoltJson.decodeFromString(
|
||||
_android.value = PeptideJson.decodeFromString(
|
||||
AndroidSpecificSettings.serializer(),
|
||||
it.value
|
||||
)
|
||||
|
|
@ -82,7 +82,7 @@ object SyncedSettings {
|
|||
private fun parseNotificationSettings(value: String): NotificationSettings {
|
||||
return try {
|
||||
var intermediate =
|
||||
RevoltJson.decodeFromString(_NotificationSettingsToParse.serializer(), value)
|
||||
PeptideJson.decodeFromString(_NotificationSettingsToParse.serializer(), value)
|
||||
|
||||
// Throw out any value of intermediate.server and .channel that isn't a string
|
||||
intermediate = intermediate.copy(
|
||||
|
|
@ -108,23 +108,23 @@ object SyncedSettings {
|
|||
|
||||
suspend fun updateOrdering(value: OrderingSettings) {
|
||||
_ordering.value = value
|
||||
setKey("ordering", RevoltJson.encodeToString(OrderingSettings.serializer(), value))
|
||||
setKey("ordering", PeptideJson.encodeToString(OrderingSettings.serializer(), value))
|
||||
}
|
||||
|
||||
suspend fun updateAndroid(value: AndroidSpecificSettings) {
|
||||
_android.value = value
|
||||
setKey("android", RevoltJson.encodeToString(AndroidSpecificSettings.serializer(), value))
|
||||
setKey("android", PeptideJson.encodeToString(AndroidSpecificSettings.serializer(), value))
|
||||
}
|
||||
|
||||
suspend fun updateNotifications(value: NotificationSettings) {
|
||||
_notifications.value = value
|
||||
setKey("notifications", RevoltJson.encodeToString(NotificationSettings.serializer(), value))
|
||||
setKey("notifications", PeptideJson.encodeToString(NotificationSettings.serializer(), value))
|
||||
}
|
||||
|
||||
suspend fun resetOrdering() {
|
||||
val default = OrderingSettings()
|
||||
_ordering.value = default
|
||||
setKey("ordering", RevoltJson.encodeToString(OrderingSettings.serializer(), default))
|
||||
setKey("ordering", PeptideJson.encodeToString(OrderingSettings.serializer(), default))
|
||||
}
|
||||
|
||||
suspend fun resetAndroid() {
|
||||
|
|
@ -134,7 +134,7 @@ object SyncedSettings {
|
|||
messageReplyStyle = "None"
|
||||
)
|
||||
_android.value = default
|
||||
setKey("android", RevoltJson.encodeToString(AndroidSpecificSettings.serializer(), default))
|
||||
setKey("android", PeptideJson.encodeToString(AndroidSpecificSettings.serializer(), default))
|
||||
}
|
||||
|
||||
suspend fun resetNotifications() {
|
||||
|
|
@ -142,7 +142,7 @@ object SyncedSettings {
|
|||
_notifications.value = default
|
||||
setKey(
|
||||
"notifications",
|
||||
RevoltJson.encodeToString(NotificationSettings.serializer(), default)
|
||||
PeptideJson.encodeToString(NotificationSettings.serializer(), default)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
package chat.revolt.api.unreads
|
||||
package chat.peptide.api.unreads
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.ULID
|
||||
import chat.revolt.api.routes.channel.ackChannel
|
||||
import chat.revolt.api.routes.server.ackServer
|
||||
import chat.revolt.api.routes.sync.syncUnreads
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.revolt.api.schemas.ChannelUnread
|
||||
import chat.revolt.api.settings.NotificationSettingsProvider
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.ULID
|
||||
import chat.peptide.api.routes.channel.ackChannel
|
||||
import chat.peptide.api.routes.server.ackServer
|
||||
import chat.peptide.api.routes.sync.syncUnreads
|
||||
import chat.peptide.api.schemas.ChannelType
|
||||
import chat.peptide.api.schemas.ChannelUnread
|
||||
import chat.peptide.api.settings.NotificationSettingsProvider
|
||||
|
||||
class Unreads {
|
||||
private val hasLoaded = mutableStateOf(false)
|
||||
|
|
@ -50,8 +50,8 @@ class Unreads {
|
|||
fun serverHasUnread(serverId: String): Boolean {
|
||||
if (!hasLoaded.value) return false
|
||||
|
||||
return RevoltAPI.serverCache[serverId]?.channels?.any {
|
||||
val channel = RevoltAPI.channelCache[it] ?: return@any false // Channel not found
|
||||
return PeptideAPI.serverCache[serverId]?.channels?.any {
|
||||
val channel = PeptideAPI.channelCache[it] ?: return@any false // Channel not found
|
||||
if (channel.channelType == ChannelType.VoiceChannel) return@any false // Channel is voice
|
||||
if (NotificationSettingsProvider.isChannelMuted(
|
||||
it,
|
||||
|
|
@ -81,7 +81,7 @@ class Unreads {
|
|||
suspend fun markServerAsRead(serverId: String, sync: Boolean = true) {
|
||||
if (!hasLoaded.value) return
|
||||
|
||||
val server = RevoltAPI.serverCache[serverId] ?: return
|
||||
val server = PeptideAPI.serverCache[serverId] ?: return
|
||||
server.channels?.forEach { channel ->
|
||||
channels[channel] = channels[channel]?.copy(last_id = ULID.makeNext()) ?: ChannelUnread(
|
||||
channel,
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package chat.revolt.c2dm
|
||||
package chat.peptide.c2dm
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationChannelGroup
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import chat.revolt.R
|
||||
import chat.peptide.R
|
||||
|
||||
// TODO
|
||||
// * Add the remaining groups.
|
||||
|
|
@ -15,10 +15,10 @@ import chat.revolt.R
|
|||
|
||||
class ChannelRegistrator(val context: Context) {
|
||||
companion object {
|
||||
const val CHANNEL_ID_GROUP_CONVERSATIONS = "chat.revolt.c2dm.conversations"
|
||||
const val CHANNEL_ID_GROUP_CONVERSATIONS = "chat.peptide.c2dm.conversations"
|
||||
|
||||
const val CHANNEL_ID_GROUP_SOCIAL = "chat.revolt.c2dm.social"
|
||||
const val CHANNEL_ID_GROUP_SOCIAL_FRIENDREQUESTS = "chat.revolt.c2dm.social.friendrequests"
|
||||
const val CHANNEL_ID_GROUP_SOCIAL = "chat.peptide.c2dm.social"
|
||||
const val CHANNEL_ID_GROUP_SOCIAL_FRIENDREQUESTS = "chat.peptide.c2dm.social.friendrequests"
|
||||
}
|
||||
|
||||
private val notificationManager =
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.c2dm
|
||||
package chat.peptide.c2dm
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
|
|
@ -10,17 +10,17 @@ import androidx.core.app.NotificationManagerCompat
|
|||
import androidx.core.app.Person
|
||||
import androidx.core.app.RemoteInput
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import chat.revolt.R
|
||||
import chat.revolt.activities.MainActivity
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.api.internals.ULID
|
||||
import chat.revolt.api.routes.push.subscribePush
|
||||
import chat.revolt.api.schemas.Message
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.revolt.c2dm.ChannelRegistrator.Companion.CHANNEL_ID_GROUP_SOCIAL_FRIENDREQUESTS
|
||||
import chat.revolt.persistence.Database
|
||||
import chat.revolt.persistence.SqlStorage
|
||||
import chat.peptide.R
|
||||
import chat.peptide.activities.MainActivity
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.PeptideJson
|
||||
import chat.peptide.api.internals.ULID
|
||||
import chat.peptide.api.routes.push.subscribePush
|
||||
import chat.peptide.api.schemas.Message
|
||||
import chat.peptide.api.schemas.User
|
||||
import chat.peptide.c2dm.ChannelRegistrator.Companion.CHANNEL_ID_GROUP_SOCIAL_FRIENDREQUESTS
|
||||
import chat.peptide.persistence.Database
|
||||
import chat.peptide.persistence.SqlStorage
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
|
|
@ -51,13 +51,13 @@ class HandlerService : FirebaseMessagingService() {
|
|||
|
||||
Log.d("HandlerService", payloadString)
|
||||
|
||||
val payload = RevoltJson.parseToJsonElement(payloadString).jsonObject
|
||||
val payload = PeptideJson.parseToJsonElement(payloadString).jsonObject
|
||||
val keys = payload.keys.toList().toString()
|
||||
Log.d("HandlerService", "following keys: $keys")
|
||||
|
||||
var authorIcon = payload["icon"]?.jsonPrimitive?.contentOrNull
|
||||
val message = payload["message"]?.jsonObject?.let {
|
||||
RevoltJson.decodeFromJsonElement(
|
||||
PeptideJson.decodeFromJsonElement(
|
||||
Message.serializer(),
|
||||
it
|
||||
)
|
||||
|
|
@ -67,7 +67,7 @@ class HandlerService : FirebaseMessagingService() {
|
|||
}
|
||||
|
||||
val user = payload["message"]?.jsonObject?.get("user")?.jsonObject?.let {
|
||||
RevoltJson.decodeFromJsonElement(
|
||||
PeptideJson.decodeFromJsonElement(
|
||||
User.serializer(),
|
||||
it
|
||||
)
|
||||
|
|
@ -78,7 +78,7 @@ class HandlerService : FirebaseMessagingService() {
|
|||
|
||||
if (authorIcon == null) {
|
||||
authorIcon =
|
||||
"${RevoltAPI.getCurrentBaseUrl()}/users/${message.author?.ifBlank { "0".repeat(26) }}/default_avatar"
|
||||
"${PeptideAPI.getCurrentBaseUrl()}/users/${message.author?.ifBlank { "0".repeat(26) }}/default_avatar"
|
||||
}
|
||||
|
||||
val db = Database(SqlStorage.driver)
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
package chat.revolt.callbacks
|
||||
package chat.peptide.callbacks
|
||||
|
||||
import chat.revolt.screens.chat.ChatRouterDestination
|
||||
import chat.peptide.screens.chat.ChatRouterDestination
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
||||
sealed class Action {
|
||||
data class OpenUserSheet(val userId: String, val serverId: String?) : Action()
|
||||
data class SwitchChannel(val channelId: String) : Action()
|
||||
data class SwitchChannel(
|
||||
val channelId: String,
|
||||
val messageId: String? = null,
|
||||
) : Action()
|
||||
data class LinkInfo(val url: String) : Action()
|
||||
data class EmoteInfo(val emoteId: String) : Action()
|
||||
data class MessageReactionInfo(val messageId: String, val emoji: String) : Action()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.callbacks
|
||||
package chat.peptide.callbacks
|
||||
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import android.icu.text.DateFormat
|
||||
import android.text.format.DateUtils
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
|
|
@ -28,10 +28,10 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.realtime.DisconnectionState
|
||||
import chat.revolt.api.settings.LoadedSettings
|
||||
import chat.revolt.ui.theme.Theme
|
||||
import chat.peptide.R
|
||||
import chat.peptide.api.realtime.DisconnectionState
|
||||
import chat.peptide.api.settings.LoadedSettings
|
||||
import chat.peptide.ui.theme.Theme
|
||||
|
||||
private val NON_MATERIAL_COLOURS = mapOf(
|
||||
DisconnectionState.Disconnected to (Color(0xff4E0C0C) to Color(0xffff1744)),
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
|
|
@ -23,14 +23,14 @@ import androidx.compose.ui.graphics.Brush
|
|||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.revolt.api.internals.BrushCompat
|
||||
import chat.revolt.api.internals.solidColor
|
||||
import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl
|
||||
import chat.revolt.api.schemas.Embed
|
||||
import chat.revolt.composables.chat.specialembeds.SpecialEmbedSwitch
|
||||
import chat.revolt.composables.generic.RemoteImage
|
||||
import chat.revolt.composables.markdown.RichMarkdown
|
||||
import chat.revolt.api.schemas.Embed as EmbedSchema
|
||||
import chat.peptide.api.internals.BrushCompat
|
||||
import chat.peptide.api.internals.solidColor
|
||||
import chat.peptide.api.routes.microservices.january.asJanuaryProxyUrl
|
||||
import chat.peptide.api.schemas.Embed
|
||||
import chat.peptide.composables.chat.specialembeds.SpecialEmbedSwitch
|
||||
import chat.peptide.composables.generic.RemoteImage
|
||||
import chat.peptide.composables.markdown.RichMarkdown
|
||||
import chat.peptide.api.schemas.Embed as EmbedSchema
|
||||
|
||||
@Composable
|
||||
fun RegularEmbed(
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.clickable
|
||||
|
|
@ -26,16 +26,16 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.solidColor
|
||||
import chat.revolt.api.routes.channel.fetchSingleMessage
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.revolt.api.settings.Experiments
|
||||
import chat.revolt.composables.generic.UserAvatar
|
||||
import chat.revolt.markdown.jbm.JBM
|
||||
import chat.revolt.markdown.jbm.JBMRenderer
|
||||
import chat.revolt.markdown.jbm.LocalJBMarkdownTreeState
|
||||
import chat.peptide.R
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.solidColor
|
||||
import chat.peptide.api.routes.channel.fetchSingleMessage
|
||||
import chat.peptide.api.schemas.User
|
||||
import chat.peptide.api.settings.Experiments
|
||||
import chat.peptide.composables.generic.UserAvatar
|
||||
import chat.peptide.markdown.jbm.JBM
|
||||
import chat.peptide.markdown.jbm.JBMRenderer
|
||||
import chat.peptide.markdown.jbm.LocalJBMarkdownTreeState
|
||||
import java.util.concurrent.CancellationException
|
||||
|
||||
@OptIn(JBM::class)
|
||||
|
|
@ -47,8 +47,8 @@ fun InReplyTo(
|
|||
withMention: Boolean = false,
|
||||
onMessageClick: (String) -> Unit = { _ -> }
|
||||
) {
|
||||
val message = RevoltAPI.messageCache[messageId]
|
||||
val author = RevoltAPI.userCache[message?.author ?: ""]
|
||||
val message = PeptideAPI.messageCache[messageId]
|
||||
val author = PeptideAPI.userCache[message?.author ?: ""]
|
||||
|
||||
val username = message?.let { authorName(it) }
|
||||
?: author?.let { User.resolveDefaultName(it) }
|
||||
|
|
@ -58,12 +58,12 @@ fun InReplyTo(
|
|||
val usernameColor =
|
||||
message?.let { authorColour(it) } ?: Brush.solidColor(contentColor)
|
||||
|
||||
val serverId = remember(channelId) { RevoltAPI.channelCache[channelId]?.server }
|
||||
val serverId = remember(channelId) { PeptideAPI.channelCache[channelId]?.server }
|
||||
|
||||
LaunchedEffect(messageId) {
|
||||
if (messageId !in RevoltAPI.messageCache) {
|
||||
if (messageId !in PeptideAPI.messageCache) {
|
||||
try {
|
||||
RevoltAPI.messageCache[messageId] = fetchSingleMessage(channelId, messageId)
|
||||
PeptideAPI.messageCache[messageId] = fetchSingleMessage(channelId, messageId)
|
||||
} catch (e: CancellationException) {
|
||||
// It's fine
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.revolt.R
|
||||
import chat.peptide.R
|
||||
|
||||
enum class InlineBadge {
|
||||
Bot,
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
|
|
@ -8,15 +8,15 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.BrushCompat
|
||||
import chat.revolt.api.internals.Roles
|
||||
import chat.revolt.api.internals.solidColor
|
||||
import chat.revolt.api.schemas.Member
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.revolt.composables.generic.UserAvatar
|
||||
import chat.revolt.composables.generic.presenceFromStatus
|
||||
import chat.revolt.internals.extensions.TransparentListItemColours
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.BrushCompat
|
||||
import chat.peptide.api.internals.Roles
|
||||
import chat.peptide.api.internals.solidColor
|
||||
import chat.peptide.api.schemas.Member
|
||||
import chat.peptide.api.schemas.User
|
||||
import chat.peptide.composables.generic.UserAvatar
|
||||
import chat.peptide.composables.generic.presenceFromStatus
|
||||
import chat.peptide.internals.extensions.TransparentListItemColours
|
||||
|
||||
@Composable
|
||||
fun MemberListItem(
|
||||
|
|
@ -74,7 +74,7 @@ fun MemberListItem(
|
|||
?: user?.id
|
||||
?: userId,
|
||||
avatar = user?.avatar,
|
||||
rawUrl = member?.avatar?.let { "${RevoltAPI.getCurrentFilesUrl()}/avatars/${it.id}" },
|
||||
rawUrl = member?.avatar?.let { "${PeptideAPI.getCurrentFilesUrl()}/avatars/${it.id}" },
|
||||
userId = userId,
|
||||
presence = presenceFromStatus(
|
||||
user?.status?.presence,
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.icu.text.DateFormat
|
||||
import android.net.Uri
|
||||
import android.text.format.DateUtils
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
|
|
@ -59,40 +60,41 @@ import androidx.compose.ui.text.style.TextDecoration
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.activities.media.ImageViewActivity
|
||||
import chat.revolt.activities.media.VideoViewActivity
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.BrushCompat
|
||||
import chat.revolt.api.internals.MessageFlag
|
||||
import chat.revolt.api.internals.Roles
|
||||
import chat.revolt.api.internals.SpecialUsers
|
||||
import chat.revolt.api.internals.ULID
|
||||
import chat.revolt.api.internals.has
|
||||
import chat.revolt.api.internals.solidColor
|
||||
import chat.revolt.api.routes.channel.react
|
||||
import chat.revolt.api.routes.channel.unreact
|
||||
import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl
|
||||
import chat.revolt.api.schemas.AutumnResource
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.revolt.api.settings.Experiments
|
||||
import chat.revolt.api.settings.LoadedSettings
|
||||
import chat.revolt.api.settings.MessageReplyStyle
|
||||
import chat.revolt.callbacks.Action
|
||||
import chat.revolt.callbacks.ActionChannel
|
||||
import chat.revolt.composables.generic.RemoteImage
|
||||
import chat.revolt.composables.generic.UserAvatar
|
||||
import chat.revolt.composables.generic.UserAvatarWidthPlaceholder
|
||||
import chat.revolt.composables.markdown.LocalMarkdownTreeConfig
|
||||
import chat.revolt.composables.markdown.RichMarkdown
|
||||
import chat.revolt.internals.text.Gigamoji
|
||||
import chat.revolt.internals.text.MessageProcessor
|
||||
import chat.revolt.markdown.jbm.JBM
|
||||
import chat.revolt.markdown.jbm.JBMRenderer
|
||||
import chat.revolt.markdown.jbm.LocalJBMarkdownTreeState
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.peptide.R
|
||||
import chat.peptide.activities.media.ImageViewActivity
|
||||
import chat.peptide.activities.media.VideoViewActivity
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.BrushCompat
|
||||
import chat.peptide.api.internals.MessageFlag
|
||||
import chat.peptide.api.internals.Roles
|
||||
import chat.peptide.api.internals.SpecialUsers
|
||||
import chat.peptide.api.internals.ULID
|
||||
import chat.peptide.api.internals.has
|
||||
import chat.peptide.api.internals.solidColor
|
||||
import chat.peptide.api.routes.channel.react
|
||||
import chat.peptide.api.routes.channel.unreact
|
||||
import chat.peptide.api.routes.microservices.january.asJanuaryProxyUrl
|
||||
import chat.peptide.api.schemas.AutumnResource
|
||||
import chat.peptide.api.schemas.User
|
||||
import chat.peptide.api.settings.Experiments
|
||||
import chat.peptide.api.settings.LoadedSettings
|
||||
import chat.peptide.api.settings.MessageReplyStyle
|
||||
import chat.peptide.callbacks.Action
|
||||
import chat.peptide.callbacks.ActionChannel
|
||||
import chat.peptide.utils.InternalLinkHandler
|
||||
import chat.peptide.composables.generic.RemoteImage
|
||||
import chat.peptide.composables.generic.UserAvatar
|
||||
import chat.peptide.composables.generic.UserAvatarWidthPlaceholder
|
||||
import chat.peptide.composables.markdown.LocalMarkdownTreeConfig
|
||||
import chat.peptide.composables.markdown.RichMarkdown
|
||||
import chat.peptide.internals.text.Gigamoji
|
||||
import chat.peptide.internals.text.MessageProcessor
|
||||
import chat.peptide.markdown.jbm.JBM
|
||||
import chat.peptide.markdown.jbm.JBMRenderer
|
||||
import chat.peptide.markdown.jbm.LocalJBMarkdownTreeState
|
||||
import chat.peptide.persistence.KVStorage
|
||||
import kotlinx.coroutines.launch
|
||||
import chat.revolt.api.schemas.Message as MessageSchema
|
||||
import chat.peptide.api.schemas.Message as MessageSchema
|
||||
|
||||
@Composable
|
||||
fun authorColour(message: MessageSchema): Brush {
|
||||
|
|
@ -101,7 +103,7 @@ fun authorColour(message: MessageSchema): Brush {
|
|||
} else {
|
||||
val defaultColour = Brush.solidColor(LocalContentColor.current)
|
||||
|
||||
val serverId = RevoltAPI.channelCache[message.channel]?.server ?: return defaultColour
|
||||
val serverId = PeptideAPI.channelCache[message.channel]?.server ?: return defaultColour
|
||||
|
||||
val highestRole = message.author?.let {
|
||||
Roles.resolveHighestRole(serverId, it, withColour = true)
|
||||
|
|
@ -119,14 +121,14 @@ fun authorName(message: MessageSchema): String {
|
|||
}
|
||||
|
||||
val serverId =
|
||||
RevoltAPI.channelCache[message.channel]?.server
|
||||
?: return RevoltAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
||||
PeptideAPI.channelCache[message.channel]?.server
|
||||
?: return PeptideAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
||||
?: stringResource(R.string.unknown)
|
||||
|
||||
val member = message.author?.let { RevoltAPI.members.getMember(serverId, it) }
|
||||
val member = message.author?.let { PeptideAPI.members.getMember(serverId, it) }
|
||||
?: return stringResource(R.string.unknown)
|
||||
return member.nickname
|
||||
?: RevoltAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
||||
?: PeptideAPI.userCache[message.author]?.let { User.resolveDefaultName(it) }
|
||||
?: stringResource(R.string.unknown)
|
||||
}
|
||||
|
||||
|
|
@ -137,22 +139,52 @@ fun authorAvatarUrl(message: MessageSchema): String? {
|
|||
}
|
||||
|
||||
val serverId =
|
||||
RevoltAPI.channelCache[message.channel]?.server ?: return null
|
||||
val member = message.author?.let { RevoltAPI.members.getMember(serverId, it) }
|
||||
PeptideAPI.channelCache[message.channel]?.server ?: return null
|
||||
val member = message.author?.let { PeptideAPI.members.getMember(serverId, it) }
|
||||
?: return null
|
||||
|
||||
return member.avatar?.let { "${RevoltAPI.getCurrentFilesUrl()}/avatars/${it.id}" }
|
||||
return member.avatar?.let { "${PeptideAPI.getCurrentFilesUrl()}/avatars/${it.id}" }
|
||||
}
|
||||
|
||||
fun viewUrlInBrowser(ctx: android.content.Context, url: String) {
|
||||
val customTab = CustomTabsIntent
|
||||
.Builder()
|
||||
.build()
|
||||
customTab.launchUrl(ctx, Uri.parse(url))
|
||||
Log.d("Message", "viewUrlInBrowser called with url: $url")
|
||||
|
||||
// Check if this is an internal link that should be handled by the app
|
||||
if (InternalLinkHandler.isInternalLink(url)) {
|
||||
Log.d("Message", "URL is an internal link, attempting to handle internally")
|
||||
|
||||
// Try to handle the link internally
|
||||
val handled = InternalLinkHandler.handleInternalLink(ctx, url, true)
|
||||
|
||||
Log.d("Message", "Internal link handled: $handled")
|
||||
|
||||
if (handled) {
|
||||
// Link was handled internally
|
||||
Log.d("Message", "Link was handled internally, returning")
|
||||
return
|
||||
} else {
|
||||
Log.d("Message", "Failed to handle link internally, falling back to browser")
|
||||
}
|
||||
} else {
|
||||
Log.d("Message", "URL is not an internal link, opening in browser")
|
||||
}
|
||||
|
||||
// If not an internal link or couldn't be handled internally, open in browser
|
||||
try {
|
||||
Log.d("Message", "Opening URL in browser")
|
||||
val customTab = CustomTabsIntent
|
||||
.Builder()
|
||||
.build()
|
||||
customTab.launchUrl(ctx, Uri.parse(url))
|
||||
Log.d("Message", "URL opened in browser successfully")
|
||||
} catch (e: Exception) {
|
||||
Log.e("Message", "Error opening URL in browser", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun viewAttachmentInBrowser(ctx: android.content.Context, attachment: AutumnResource) {
|
||||
val url = "${RevoltAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
val url =
|
||||
"${PeptideAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
viewUrlInBrowser(ctx, url)
|
||||
}
|
||||
|
||||
|
|
@ -186,6 +218,7 @@ fun formatLongAsTime(time: Long): String {
|
|||
@OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class, JBM::class)
|
||||
@Composable
|
||||
fun Message(
|
||||
modifier: Modifier = Modifier,
|
||||
message: MessageSchema,
|
||||
onMessageContextMenu: () -> Unit = {},
|
||||
onAvatarClick: () -> Unit = {},
|
||||
|
|
@ -195,9 +228,8 @@ fun Message(
|
|||
onAddReaction: () -> Unit = {},
|
||||
fromWebhook: Boolean = false,
|
||||
webhookName: String? = null,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val author = RevoltAPI.userCache[message.author] ?: return CircularProgressIndicator()
|
||||
val author = PeptideAPI.userCache[message.author] ?: return CircularProgressIndicator()
|
||||
val context = LocalContext.current
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
@ -229,8 +261,8 @@ fun Message(
|
|||
var mentionsSelfRole by remember(message) { mutableStateOf(false) }
|
||||
LaunchedEffect(Unit) {
|
||||
val serverId =
|
||||
RevoltAPI.channelCache[message.channel]?.server ?: return@LaunchedEffect
|
||||
var selfMember = RevoltAPI.selfId?.let { RevoltAPI.members.getMember(serverId, it) }
|
||||
PeptideAPI.channelCache[message.channel]?.server ?: return@LaunchedEffect
|
||||
var selfMember = PeptideAPI.selfId?.let { PeptideAPI.members.getMember(serverId, it) }
|
||||
?: return@LaunchedEffect
|
||||
var messageRoleMentions = MessageProcessor.findMentionedRoleIDs(message.content)
|
||||
|
||||
|
|
@ -280,7 +312,7 @@ fun Message(
|
|||
} else {
|
||||
Column(
|
||||
modifier = Modifier.then(
|
||||
if ((message.mentions?.contains(RevoltAPI.selfId) == true)
|
||||
if ((message.mentions?.contains(PeptideAPI.selfId) == true)
|
||||
|| mentionsSelfRole
|
||||
|| message.flags has MessageFlag.MentionsOnline
|
||||
|| message.flags has MessageFlag.MentionsEveryone
|
||||
|
|
@ -294,7 +326,7 @@ fun Message(
|
|||
)
|
||||
) {
|
||||
message.replies?.forEach { reply ->
|
||||
val replyMessage = RevoltAPI.messageCache[reply]
|
||||
val replyMessage = PeptideAPI.messageCache[reply]
|
||||
|
||||
message.channel?.let { chId ->
|
||||
InReplyTo(
|
||||
|
|
@ -430,7 +462,7 @@ fun Message(
|
|||
if (Experiments.useKotlinBasedMarkdownRenderer.isEnabled) {
|
||||
CompositionLocalProvider(
|
||||
LocalJBMarkdownTreeState provides LocalJBMarkdownTreeState.current.copy(
|
||||
currentServer = RevoltAPI.channelCache[message.channel]?.server,
|
||||
currentServer = PeptideAPI.channelCache[message.channel]?.server,
|
||||
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
||||
message.content
|
||||
)
|
||||
|
|
@ -445,7 +477,7 @@ fun Message(
|
|||
} else {
|
||||
CompositionLocalProvider(
|
||||
LocalMarkdownTreeConfig provides LocalMarkdownTreeConfig.current.copy(
|
||||
currentServer = RevoltAPI.channelCache[message.channel]?.server,
|
||||
currentServer = PeptideAPI.channelCache[message.channel]?.server,
|
||||
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
||||
message.content
|
||||
)
|
||||
|
|
@ -516,9 +548,12 @@ fun Message(
|
|||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Embed(embed = embed, onLinkClick = {
|
||||
viewUrlInBrowser(context, it)
|
||||
})
|
||||
Embed(
|
||||
embed = embed,
|
||||
onLinkClick = {
|
||||
viewUrlInBrowser(context, it)
|
||||
}
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.text.format.Formatter
|
||||
|
|
@ -32,11 +32,11 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.schemas.AutumnResource
|
||||
import chat.revolt.composables.generic.RemoteImage
|
||||
import chat.revolt.composables.media.AudioPlayer
|
||||
import chat.peptide.R
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.schemas.AutumnResource
|
||||
import chat.peptide.composables.generic.RemoteImage
|
||||
import chat.peptide.composables.media.AudioPlayer
|
||||
import dev.chrisbanes.haze.hazeEffect
|
||||
import dev.chrisbanes.haze.hazeSource
|
||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
|
|
@ -83,7 +83,7 @@ fun FileAttachment(attachment: AutumnResource) {
|
|||
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||
@Composable
|
||||
fun ImageAttachment(attachment: AutumnResource) {
|
||||
val url = "${RevoltAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
val url = "${PeptideAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
var spoilerShown by remember { mutableStateOf(false) }
|
||||
val hazeState =
|
||||
if (attachment.filename?.startsWith("SPOILER_") == true) rememberHazeState() else null
|
||||
|
|
@ -149,7 +149,7 @@ fun VideoPlayButton() {
|
|||
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||
@Composable
|
||||
fun VideoAttachment(attachment: AutumnResource) {
|
||||
val url = "${RevoltAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
val url = "${PeptideAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
|
||||
BoxWithConstraints {
|
||||
Box(
|
||||
|
|
@ -179,7 +179,7 @@ fun VideoAttachment(attachment: AutumnResource) {
|
|||
|
||||
@Composable
|
||||
fun AudioAttachment(attachment: AutumnResource) {
|
||||
val url = "${RevoltAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
val url = "${PeptideAPI.getCurrentFilesUrl()}/attachments/${attachment.id}/${attachment.filename}"
|
||||
AudioPlayer(
|
||||
url = url,
|
||||
filename = attachment.filename ?: "Audio",
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
|
|
@ -79,17 +79,17 @@ import androidx.compose.ui.text.input.KeyboardType
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.activities.RevoltTweenFloat
|
||||
import chat.revolt.activities.RevoltTweenInt
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.BrushCompat
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.revolt.api.schemas.Member
|
||||
import chat.revolt.composables.generic.RemoteImage
|
||||
import chat.revolt.composables.generic.UserAvatar
|
||||
import chat.revolt.composables.screens.chat.ChannelIcon
|
||||
import chat.revolt.internals.Autocomplete
|
||||
import chat.peptide.R
|
||||
import chat.peptide.activities.PeptideTweenFloat
|
||||
import chat.peptide.activities.PeptideTweenInt
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.BrushCompat
|
||||
import chat.peptide.api.schemas.ChannelType
|
||||
import chat.peptide.api.schemas.Member
|
||||
import chat.peptide.composables.generic.RemoteImage
|
||||
import chat.peptide.composables.generic.UserAvatar
|
||||
import chat.peptide.composables.screens.chat.ChannelIcon
|
||||
import chat.peptide.internals.Autocomplete
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
fun Pair<Int, Int>.asTextRange(): TextRange {
|
||||
|
|
@ -111,25 +111,25 @@ private fun CharSequence.lastWordStartsAt(): Int {
|
|||
|
||||
sealed class AutocompleteSuggestion {
|
||||
data class User(
|
||||
val user: chat.revolt.api.schemas.User,
|
||||
val user: chat.peptide.api.schemas.User,
|
||||
val member: Member?,
|
||||
val query: String
|
||||
) : AutocompleteSuggestion()
|
||||
|
||||
data class Channel(
|
||||
val channel: chat.revolt.api.schemas.Channel,
|
||||
val channel: chat.peptide.api.schemas.Channel,
|
||||
val query: String
|
||||
) : AutocompleteSuggestion()
|
||||
|
||||
data class Emoji(
|
||||
val shortcode: String,
|
||||
val unicode: String?,
|
||||
val custom: chat.revolt.api.schemas.Emoji?,
|
||||
val custom: chat.peptide.api.schemas.Emoji?,
|
||||
val query: String
|
||||
) : AutocompleteSuggestion()
|
||||
|
||||
data class Role(
|
||||
val role: chat.revolt.api.schemas.Role,
|
||||
val role: chat.peptide.api.schemas.Role,
|
||||
val id: String,
|
||||
val query: String
|
||||
) : AutocompleteSuggestion()
|
||||
|
|
@ -318,7 +318,7 @@ fun MessageField(
|
|||
userId = item.user.id ?: "",
|
||||
avatar = item.user.avatar,
|
||||
rawUrl = item.member?.avatar?.id?.let {
|
||||
"${RevoltAPI.getCurrentFilesUrl()}/avatars/$it"
|
||||
"${PeptideAPI.getCurrentFilesUrl()}/avatars/$it"
|
||||
},
|
||||
size = SuggestionChipDefaults.IconSize,
|
||||
)
|
||||
|
|
@ -444,7 +444,7 @@ fun MessageField(
|
|||
)
|
||||
} else {
|
||||
RemoteImage(
|
||||
url = "${RevoltAPI.getCurrentFilesUrl()}/emojis/${item.custom?.id}",
|
||||
url = "${PeptideAPI.getCurrentFilesUrl()}/emojis/${item.custom?.id}",
|
||||
description = null,
|
||||
contentScale = ContentScale.Fit,
|
||||
modifier = Modifier
|
||||
|
|
@ -606,18 +606,18 @@ fun MessageField(
|
|||
full.height
|
||||
)
|
||||
}) + slideInHorizontally(
|
||||
animationSpec = RevoltTweenInt,
|
||||
animationSpec = PeptideTweenInt,
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = RevoltTweenFloat),
|
||||
) + fadeIn(animationSpec = PeptideTweenFloat),
|
||||
exit = shrinkOut(targetSize = { full ->
|
||||
IntSize(
|
||||
0,
|
||||
full.height
|
||||
)
|
||||
}) + slideOutHorizontally(
|
||||
animationSpec = RevoltTweenInt,
|
||||
animationSpec = PeptideTweenInt,
|
||||
targetOffsetX = { it }
|
||||
) + fadeOut(animationSpec = RevoltTweenFloat)
|
||||
) + fadeOut(animationSpec = PeptideTweenFloat)
|
||||
) {
|
||||
Icon(
|
||||
painter = when {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
|
|
@ -28,9 +28,9 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.isUlid
|
||||
import chat.revolt.composables.generic.RemoteImage
|
||||
import chat.peptide.api.PeptideAPI
|
||||
import chat.peptide.api.internals.isUlid
|
||||
import chat.peptide.composables.generic.RemoteImage
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
|
|
@ -40,11 +40,11 @@ fun Reaction(
|
|||
onClick: (Boolean) -> Unit,
|
||||
onLongClick: () -> Unit
|
||||
) {
|
||||
val hasOwn = members.contains(RevoltAPI.selfId)
|
||||
val hasOwn = members.contains(PeptideAPI.selfId)
|
||||
|
||||
val background by animateColorAsState(
|
||||
targetValue = if (hasOwn) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
MaterialTheme.colorScheme.secondary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surfaceContainer
|
||||
},
|
||||
|
|
@ -52,7 +52,7 @@ fun Reaction(
|
|||
)
|
||||
val foreground by animateColorAsState(
|
||||
targetValue = if (hasOwn) {
|
||||
MaterialTheme.colorScheme.onPrimary
|
||||
MaterialTheme.colorScheme.onSecondaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onSurface
|
||||
},
|
||||
|
|
@ -73,7 +73,7 @@ fun Reaction(
|
|||
CompositionLocalProvider(LocalContentColor provides foreground) {
|
||||
if (emoji.isUlid()) {
|
||||
RemoteImage(
|
||||
url = "${RevoltAPI.getCurrentFilesUrl()}/emojis/${emoji}",
|
||||
url = "${PeptideAPI.getCurrentFilesUrl()}/emojis/${emoji}",
|
||||
description = null,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package chat.revolt.composables.chat
|
||||
package chat.peptide.composables.chat
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue